父子進程數據共享問題

1、fork
  1. #include <sys/types.h>  
  2. #include <unistd.h>  
  3. pid_t fork (void );  
正確返回:父進程中返回子進程的進程號;子進程中返回0
錯誤返回:-1;
       子進程是父進程的一個拷貝。子進程從父進程那得到了數據段和堆棧段,但不是與父進程共享而是單獨分配內存。fork函數返回後,子進程和父進程都是從fork函數的下一條語句開始執行。由於子進程與父進程的運行是無關的,父進程可先於子進程運行,子進程也可先於父進程運行。
       fork在linux下使用了寫時複製技術,剛開始共享父進程的數據段,在寫數據段的時候才進行復制。
 
 
2、vfork
  1. #include <sys/types.h>  
  2. #include <unistd.h>  
  3. 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執行刪除了不必要的複製。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章