1、fork
[cpp]
#include <sys/types.h>
#include <unistd.h>
pid_t fork (void );
#include <sys/types.h>
#include <unistd.h>
pid_t fork (void );正確返回:父進程中返回子進程的進程號;子進程中返回0
錯誤返回:-1;
子進程是父進程的一個拷貝。子進程從父進程那得到了數據段和堆棧段,但不是與父進程共享而是單獨分配內存。fork函數返回後,子進程和父進程都是從fork函數的下一條語句開始執行。由於子進程與父進程的運行是無關的,父進程可先於子進程運行,子進程也可先於父進程運行。
fork在linux下使用了寫時復制技術,剛開始共享父進程的數據段,在寫數據段的時候才進行復制。
2、vfork
[cpp]
#include <sys/types.h>
#include <unistd.h>
pid_t vfork (void );
#include <sys/types.h>
#include <unistd.h>
pid_t vfork (void );返回值同上
vfork創建新進程的主要目的在於用exec函數執行另外的程序,實際上,在沒調用exec或exit之前子進程與父進程共享數據段。在vfork調用中,子進程先運行,父進程掛起,直到子進程調用exec或exit,在這以後,父子進程的執行順序不再有限制。
區別:
1、fork()創建的子進程是父進程的副本。即子進程獲取父進程數據空間,堆和 棧的副本。父子進程之間不共享這些存儲空間。而vfork()創建的進程並不將父進程的地址空間完全復制到子進程中,因為子進程會立即調用exec(或exit),於是也就不會存放該地址空間。相反,在子進程調用exec或exit之前,它在父進程的空間進行。
2、vfork()與fork()另一個區別就是:vfork保證子進程先運行,在調用exec或exit之前與父進程數據是共享的,在它調用exec或exit之後父進程才可能被調度運行;而fork的父子進程是同級別的,沒有前後限制。vfork保證子進程先運行,如果子進程依賴於父進程的進一步動作,則會導致死鎖。
3、實例:
a、現在 P1 用 fork() 函數為進程創建一個子進程 P2 ,內核:( 1 )復制 P1 的代碼段(正文段),數據段,堆,棧這四個部分。( 2)為這四個部分分配物理塊, P2 的代碼段指向P1的代碼段的物理塊,其實就是不為 P2 分配代碼段塊,數據段指向P2 自己的數據段(為其分配對應的塊),堆指向 P2 自己的堆,棧指向P2 自己的棧。如下圖所示:同左到右大的方向箭頭表示復制內容。
圖1
b、寫時復制技術:內核只為新生成的子進程創建虛擬空間,它們來復制於父進程的虛擬空間,但是不為這些段分配物理空間,它們共享父進程的物理空間,當父子進程中有寫內存的行為發生時,再為子進程相應的段分配物理空間。
圖2
c、 vfork() :這個更加激進,子進程的虛擬地址空間也不用創建,直接共享父進程的虛擬空間。這也是為後續的exec執行刪除了不必要的復制。