fork()函數 —— 父子進程資源


fork()函數功能——創建新進程

1、父子進程有獨立的數據段、堆、棧,共享代碼段

  Linux中每個進程都有4G的虛擬地址空間(獨立的3G用戶空間和共享的1G內核空間),fork()創建的子進程也不例外。子進程資源的由來:

  1、1G內核空間既然是所有進程共享,因此fork()創建的子進程自然也將擁有;

  2、3G的用戶空間是從父進程進程而來。

  fork()創建子進程時繼承了父進程的數據段、代碼段、棧段、堆,注意從父進程繼承來的是虛擬地址空間,同時也復制了頁表(沒有復制物理塊)。因此,此時父子進程擁有相同的虛擬地址,映射的物理內存也是一致的(獨立的虛擬地址空間,共享父進程的物理內存)。

  由於父進程和子進程共享物理頁面,內核將其標記為“只讀”(類似mmap)的private的方式),父子雙方均無法對其修改。無論父進程和子進程何時試圖對一個共享的頁面執行寫操作,就產生一個錯誤,這時內核就把這個頁復制到一個新的頁面給這個進程,並標記為可寫,同時修改頁表,把原來的只讀頁面標記為“可寫”,留給另外一個進程使用——寫時復制技術。

  注意:內核在為子進程分配物理內存時,並沒有將代碼段對應的數據另外復制一份給子進程,最終父子進程代碼段映射的是同一塊物理內存(代碼段在單個進程內部本來就是只讀的)。  

  每個進程的虛擬地址空間都可以是0到4G,只不過其中只有一部分有權訪問,每個進程可以有不同的映射。兩次運行同一個程序就是使用的相同的虛擬地址,但是映射到的物理地卻是不一樣的。每個進程都有自己的虛擬地址空間,不同進程的相同的虛擬地址顯然可以對應不同的物理地址。因此地址相同(虛擬地址)而值不同沒什么奇怪。

寫時復制技術參見:http://www.cnblogs.com/wuchanming/p/4495479.html

2、一次調用兩次執行

  參見:http://blog.csdn.net/shenwansangz/article/details/39184789

3、 競爭條件

  Linux是一個多用戶操作系統,在同一時間會有許多的用戶在爭奪系統的資源.有時進程為了早一點完成任務就創建子進程來爭奪資源. 一旦子進程被創建,父子進程一起從fork處繼續執行,相互競爭系統的資源.有時候我們希望子進程繼續執行,而父進程阻塞,直到子進程完成任務.這個時候我們可以調用wait或者waitpid系統調用.

  對子進程來說,fork返回給它0,但它的pid絕對不會是0;之所以fork返回0給它,是因為它隨時可以調用getpid()來獲取自己的pid;fork之后父子進程除非采用了同步手段,否則不能確定誰先運行,也不能確定誰先結束。認為子進程結束后父進程才從fork返回的,這是不對的,fork不是這樣的,vfork才這樣。

4、fork之后跟隨exec

  fork()會產生一個和父進程完全相同的子進程,但子進程在此后多會exec系統調用,出於效率考慮,linux中引入了“寫時復制“技術,也就是只有進程空間的各段的內容要發生變化時,才會將父進程的內容復制一份給子進程。由於寫時復制,在fork之后exec之前兩個進程有獨立的虛擬地址空間,共享物理內存。只有其中一方需要寫操作時,再為子進程的數據段、棧、堆分配物理空間。但在子進程上調用exec時,會清空棧、堆,以及和父進程共享的空間,重新加載新的代碼段,這樣避免了“寫時復制”拷貝共享頁面的機會,父進程也同時獨自擁有了原來共享的物理內存(可對其讀寫操作)。

  fork出來子進程之后,父子進程哪個先調度直接決定了是否需要拷貝的問題?內核一般會先調度子進程,因為很多情況下子進程是要馬上執行exec,而避免無用的復制。如果父進程先調度很可能寫共享頁面,會產生“寫時復制”的無用功。所以,一般是子進程先調度滴。

  在網上看到還有個細節問題就是,fork之后內核會通過將子進程放在隊列的前面,以讓子進程先執行,以免父進程執行導致寫時復制,而后子進程執行exec系統調用,因無意義的復制而造成效率的下降。

  如果不是因為exec,子進程執行時很可能修改內存,內核會給子進程的數據段、堆棧段分配相應的物理空間(至此兩者有各自的進程空間,互不影響),而代碼段繼續共享父進程的物理空間(兩者的代碼完全相同)。而如果是因為exec,由於兩者執行的代碼不同,子進程的代碼段也會分配單獨的物理空間。

 

5、fork()函數的實現過程

  http://blog.csdn.net/shenwansangz/article/details/39184789


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM