Can you summarize the following document?
        
  在多工作業系統中,行程(執行的程式)需要一種方法來建立新程序,例如執行其他程式。Fork及其變種在類Unix系統中通常是這樣做的唯一方式。如果程序需要啟動另一個程式的可執行檔案,它需要先Fork來建立一個自身的副本。然後由該副本即“子程序”呼叫exec系統呼叫,用其他程式覆蓋自身:停止執行自己之前的程式並執行其他程式。  Fork操作會為子程序建立一個單獨的定址空間。子程序擁有父程序所有記憶體段的精確副本。在現代的UNIX變種中,這遵循出自SunOS-4.0的虛擬記憶體模型,根據寫入時複製語義,實體記憶體不需要被實際複製。取而代之的是,兩個程序的虛擬記憶體頁面可能指向實體記憶體中的同一個頁,直到它們寫入該頁時,寫入才會發生。在用fork配合exec來執行新程式的情況下,此優化很重要。通常來說,子程序在停止程式執行前會執行一小組有利於其他程式的操作,它可能用到少量的其父程序的資料結構。  當一個程序呼叫fork時,它被認為是父程序,新建立的程序是它的孩子(子程序)。在fork之後,兩個程序還執行著相同的程式,都像是呼叫了該系統呼叫一般恢復執行。然後它們可以檢查呼叫的返回值確定其狀態:是父程序還是子程序,以及據此行事。  fork系統呼叫在第一個版本的Unix就已存在,它借用於更早的GENIE 分時系統。Fork是標準化的POSIX的一部分。

  子程序從父程序的檔案描述符副本開始。對於程序間通訊,父程序通常會建立一個或多個管道,在fork程序之後,程序關閉它們不需要的管道端。

  

  Vfork是與fork具有相同呼叫約定和很多相同語義的一個變種,但只能在有限的情況下使用它。它起源於Unix的3BSD版本,這是首個支援虛擬記憶體的Unix版本。它已按POSIX標準化,這使得vfork能具有與fork完全相同的行為。但這已在2004年的版本中被標為過時,並在後續版本中被posix_spawn()取代(其通常通過vfork實現)。  在發出一個vfork系統呼叫時,父程序被暫停,直至子程序完成執行或被新的可執行映像取代(通過系統呼叫之“exec”家族中的一項)。子程序借用父程序的MMU設定和記憶體頁面,在父程序與子程序之間共享,不進行復制,尤其是沒有寫入時複製語義;因此,如果子程序在任何共享頁面中進行修改,不會建立新的頁面,並且修改的頁面對父程序同樣可見。因為沒有頁面複製(消耗額外的記憶體),此技術在純複製環境中使用exec時較普通fork更優化。在POSIX中,除非是將立即呼叫exec家族(及其他幾個操作)的函式,其他任何目的會導致未定義行為。使用vfork時,子程序借用而非複製資料結構,所以vfork仍比使用寫時複製語義的fork更快。  System V在System VR4被引入前不支援此係統函式,因為它的記憶體共享容易出錯:同樣,Linux對vfork的手冊頁面強烈不鼓勵它的使用:使用vfork的其他問題包括死鎖,它可能發生在多執行緒程式中,由於與動態連結互動。 作為vfork介面的替代品,POSIX引入了posix_spawn函式家族,它結合了fork和exec的動作。這些函式可以實現為fork的程式庫例程,就像Linux那樣,或者為了更好的效能實現為vfork,就像Solaris那樣。不過,POSIX規範中註明它是“為核心操作設計”,尤其是用於執行在受限硬體和實時系統上的作業系統。  雖然4.4BSD的實現中擺脫了vfork的實現,使vfork做到與fork相同的行為,它在NetBSD作業系統中因效能原因而恢復。  一些嵌入式作業系統(例如uClinux)省略fork並只實現vfork,因為它們需要在由於缺乏記憶體管理單元(MMU)而不可能實現寫時複製的裝置上操作。

  Plan 9作業系統由Unix的設計者創造,包括fork,但也有一個名為“rfork”的變種,它允許父程序與子程序之間資源的細粒度共享,包括地址空間(除了呼叫棧段,那是每個程序獨有的)、環境變數和檔案系統名稱空間;這使它成為了建立程序和其中的執行緒的一個統一介面。 在FreeBSD和IRIX中採用了來自Plan 9的rfork,後者將其更名為“sproc”。

  “clone”(克隆)是Linux核心中的一個系統呼叫,它建立一個可以與其父共享“執行上下文”的子程序。類似FreeBSD的rfork和IRIX的sproc,Linux的clone受到了Plan 9的rfork啟發,並可用於實現執行緒(儘管應用程式的程式設計師通常使用更高階的介面,例如pthreads,實現在clone的頂層)。出自Plan 9和IRIX的“separate stacks”(單獨堆疊)特性已被省略,因為其導致了太多開銷(據Linus Torvalds)。

  在VMS作業系統(1977年)的原始設計中,新程序根據當前一些特定地址進行復制來建立被認為是有風險的。當前程序中的錯誤狀態可能被複制給子程序。因此在這裡使用了程序“產卵”(spawning)之隱喻:新程序的每個元件的記憶體佈局都是重新建立的。spawn後來被微軟的作業系統採用(1993年)。  VM/CMS(OpenExtensions)的POSIX相容元件提供了一個非常有限的fork實現,其中的父程序在子程序執行時被暫停,並且子與父共享同一地址空間。這本質上是一個名為fork的vfork。(注意,這隻適用於CMS客戶機作業系統,其他VM客戶機作業系統如Linux提供標準的fork功能。)

  下列Hello World程式的變種以C語言展示了fork系統呼叫的機理。該程式為兩個程序,每個都基於系統呼叫的返回值決定它們執行什麼功能。樣板程式碼中的標頭檔案等已被省略。下面是該程式的解析:呼叫中的第一句是呼叫系統呼叫來分割執行為兩個程序。的返回值被記錄在型別為pid_t的變數中,其中是POSIX型別的程序識別符號(PID)。  在計算機領域,尤其是Unix及類Unix系統作業系統中,fork是一種建立自身行程副本的操作。它通常是核心實現的一種系統呼叫。Fork是在類Unix作業系統上建立程序的一種主要方法,甚至歷史上曾是唯一方法。  -1錯誤表示出錯:沒有新程序被建立。因此要印出一條錯誤訊息。  如果成功,那麼現在有兩個程序。兩者都從返回時開始執行函式。為了使程序執行不同的任務,程式必須基於的返回值決定其作為子程序或父程序執行某個分支。 Fork操作會為子程序建立一個單獨的定址空間。子程序擁有父程序所有記憶體段的精確副本。在現代的UNIX變種中,這遵循出自SunOS-4.0的虛擬記憶體模型,根據寫入時複製語義,實體記憶體不需要被實際複製。取而代之的是,兩個程序的虛擬記憶體頁面可能指向實體記憶體中的同一個頁,直至它們寫入該頁時,寫入才會發生。在用配合來執行新程式的情況下,此優化很重要。通常,子程序在停止程式執行前會執行一小組有利於其他程式的操作,它可能用到少量的其父程序的資料結構。其他程序——即父程序,會收到傳來的子程序的程序識別符號,其始終為一個正數。父程序將此識別符號傳遞給 waitpid 系統呼叫來暫停執行,直至子程序退出。當此情況發生後,父程序繼續執行並按return語句的含義退出。
在計算機領域中,尤其是Unix及類Unix系統作業系統中,fork(程序複製)是一種建立自身行程副本的操作。它通常是核心實現的一種系統呼叫。Fork是類Unix作業系統上建立程序的一種主要方法,甚至歷史上是唯一方法。