在fork之後,子進程和父進程都會繼續執行fork調用之後的指令。子進程是父進程的副本。它將獲得父進程的數據空間,堆和棧的副本,這些都是副本,父子進程並不共享這部分的內存。也就是說,子進程對父進程中的同名變量進行修改並不會影響其在父進程中的值。 但是父子進程又共享一些東西,簡單說來就是程序的正文段。正文段存放著由cpu執行的機器指令,通常是read-only的。
由於在fork之後我們常常都是跟個exec在後面,所以為了提高效率,很多的實現並不完全復制數據段和堆、棧,而是采用寫時復制,有點類似於某些cache與內存數據的同步方法。
另一種提高效率的方法就是使用vfork,vfork最早起源於2.9BSD,它與fork的不同就在於它並不將父進程的地址空間完全復制到子進程中,因為子進程會立即調用exec.vfork出來的子進程是在父進程的空間中運行的,它的存在就是為了exec調用,所以它不需要復制這些東西,因為復制了也沒有用。如果這時子進程修改了某個變量,這將影響到父進程。
vfork與fork的另一區別是:vfork保證子進程先運行,在它調用exec或exit後父進程才可能調度運行。而fork的父子進程運行順序是不定的,它取決於內核的調度算法。
所以,fork的時候,程序代碼被復用了——我指的程序代碼就是由cpu執行的機器指令部分,這與有多少個進程在運行無關,即使是頻繁執行的程序在存儲器中也只需一個副本,而且它在執行期可能是read-only的。當然,如果你exec了,那就是另一碼事了。
另外,父進程中的數據空間和堆、棧可能會產生副本,具體情況要看你使用的是vfork還是fork.fork會產生副本,而vfork則共享這部分內存。
Trackback: http://tb.blog.csdn.net/TrackBack.ASPx?PostId=1513176