進程創建

1、許多其它操作系統提供spawn產生進程的機制。

而Unix採用與衆不同的方式,它把上述步驟分解到兩個單獨的函數中去執行:fork()和exec()。

首先,fork()通過拷貝當前進程創建一個子進程、子進程與父進程的唯一區別就在一進程ID。PID、PPID(父進程進程號)

exec()函數負責讀取可執行文件並將其載入地址空間開始運行。



2、寫時拷貝
傳統的fork()系統調用直接把所有的資源賦值給新創建的進程。這種實現過於簡單並效率低下。因爲他拷貝的數據也許並不共享,更糟糕的是如果新進程打算立即執行一個新的映像,那麼所有的拷貝都將成爲無用功。

Linux的fork()使用寫時複製技術。寫時拷貝是一種可以推遲甚至免除拷貝數據的一種技術。內核此時並不複製整個進程地址空間,而是讓父子進程共享同一份拷貝。

只有在需要寫入的時候,數據纔會被複制,從而使整個進程擁有各自的拷貝。也就是說資源的複製只有在需要寫入的時候纔會進行。在此之前,只是以只讀的方式共享。當需要

寫入的時候,內核將複製一份副本,設置爲可寫,並修改相應的頁表。這種技術使地址空間上的頁拷貝被推遲到實際發生寫入的時候才進行。在頁根本不會被寫入的情況下,他們就無需複製了。(比如fork()後立即調用exec())



3、fork()

fork()通過clone()系統調用實現。這個調用通過一系列的參數來標誌指明父子進程需要共享的資源。

fork()的實際開銷就是拷貝父進程的頁表以及給予子進程創建唯一的進程描述符。

fork()、vfork()、和__clone()庫函數都根據各自的需要的參數去調用clone(),然後由clone()去掉用do_fork()

do_fork()完成了創建中大部分的工作。它的定義在kernel/fork.c文件中。該函數調用copy_process()函數,然後讓進程開始運行。



4、vfork()

除了不拷貝父進程的頁表項外,vfork()系統調用和fork()的功能相同。

子進程作爲父進程的一個單獨的線程在它的地址空間運行。

父進程被阻塞,直到子進程退出或者執行exec()。

子進程不能向地址空間寫入。

現代由於執行fork()引入了寫時拷貝技術並且明確了子進程先運行,vfork() 的好處就僅限於不拷貝父進程的頁表項了。

如果linux將來fork()有了寫時拷貝頁表項,那麼vfork()就可以徹底退休了。





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