fork() 和 vfork() 有什麼區別?
我想詳細了解 fork() 和 vfork() 之間的區別。我無法完全消化手冊頁。
我還想澄清一下我的一位同事評論“在目前的 Linux 中,沒有 vfork(),即使你呼叫它,它也會在內部呼叫 fork()。”
手冊頁通常是簡潔的參考文件。維基百科是尋求概念解釋的更好地方。
fork 複製一個程序:它創建一個與父程序幾乎相同的子程序(最明顯的區別是新程序具有不同的程序ID)。特別是,fork(概念上)必須複製所有父程序的記憶體。
由於這相當昂貴,因此發明了 vfork 來處理不需要複製的常見特殊情況。通常,子程序做的第一件事是載入一個新的程序映像,所以會發生以下情況:
if (fork()) { # parent process … } else { # child process (with a new copy of the process memory) execve("/bin/sh", …); # discard the process memory }
該
execve
呼叫載入了一個新的可執行程序,這用新的可執行程序的程式碼和新的數據儲存器替換了程序的程式碼和數據儲存器。所以創建的整個記憶體副本fork
都是徒勞的。於是
vfork
就發明了這個叫法。它不會複製記憶體。因此vfork
很便宜,但很難使用,因為您必須確保您不訪問子程序中的任何程序堆棧或堆空間。請注意,即使讀取也可能是一個問題,因為父程序一直在執行。例如,此程式碼被破壞(它可能會或可能不會工作,具體取決於孩子或父母是否首先獲得時間片):if (vfork()) { # parent process cmd = NULL; # modify the only copy of cmd } else { # child process execve("/bin/sh", "sh", "-c", cmd, (char*)NULL); # read the only copy of cmd }
自 vfork 發明以來,已經發明了更好的優化。大多數現代系統,包括 Linux,都使用一種寫時複製的形式,其中程序記憶體中的頁面在
fork
呼叫時不會被複製,而是在隨後父或子第一次寫入頁面時複製。也就是說,每個頁面一開始都是共享的,並且在任一程序寫入該頁面之前一直保持共享狀態;寫入的程序獲得一個新的物理頁面(具有相同的虛擬地址)。寫時複製使 vfork 幾乎無用,因為在可用fork
的情況下不會製作任何副本。vfork
Linux 確實保留了 vfork。系統
fork
呼叫仍然必須複製程序的虛擬記憶體表,即使它不複製實際記憶體;vfork
甚至不需要這樣做。在大多數應用程序中,性能改進可以忽略不計。