理解vfork函式

2021-08-13 11:13:42 字數 2187 閱讀 5722

vfork這個函式,起初是在fork函式沒有實現寫實拷貝機制的時候出現的乙個東西。然而現在的fork的函式早已經支援寫實拷貝。

提到寫實拷貝就多說幾句,在作業系統中,建立乙個子程序你就得給他分配程序所需的資源,如果每次建立子程序後都要拷貝父程序的資源有點太降低效率了。就是在這個環境下衍生出了vfork這個函式,父子程序同時使用同乙份記憶體空間,雖然省去了重新開闢和拷貝的動作,但卻非常危險。

寫實拷貝

在後來的發展中,fork實現了寫實拷貝的機制,即建立乙個子程序後先不給它分配資源,直到父程序或者子程序要進行資料的讀寫時再進行記憶體的開闢和拷貝父程序**段和資料段。

vfork函式

#include

#include

pid_d vork(void);

函式特點

本篇文章主要**,為什麼要有這兩條規則?

父程序影響子程序:對於這一點vfork函式在底層實現,就確保子程序一定先與父程序執行,所以父程序影響子程序這一點,作業系統幫助我們搞定了。

如何防止子程序影響到父程序

vfork函式的設計初衷就是建立乙個子程序,為了提高效率不給它開闢空間,父子共用,然後子程序直接呼叫exec函式族去做其他事,因為一旦呼叫exec程式替換,子程序就去執行別的函式,不會再影響父程序。

為什麼必須時_exit/exit函式而不能是return呢?

_exit/exit與return的區別

exit在最後也會呼叫_exit函式,只不過會做一些清理工作,比如重新整理緩衝區。呼叫這兩個函式是直接將程序終止掉。

而return的話是釋放區域性變數,釋放棧幀,回到上乙個函式呼叫的位置。

那麼看一下下面這段**:

子程序修改了全域性變數的值,然後通過exit退出,可以看到父子程序列印出來的g_val都是被修改過的,可見父子程序共用乙個位址控制空間,通過exit函式退出,程式正常。

然後試著讓子程序通過return退出,看下效果。

父子程序也都列印了結果,但是最後卻報了段錯誤,想想為什麼?

呼叫return返回時,會調整ebp和exp兩個暫存器,釋放堆疊空間,釋放區域性變數。因為g_val是乙個全域性變數,儲存在靜態全域性區,所以父程序最後列印的是被子程序修改過的值。

如果子程序修改的是區域性變數的值並且return呢?

因為子程序先執行,將p_val修改為2然後列印,最後呼叫return返回,當父程序執行時,對應的位址空間處就像什麼都沒發生一樣,所以它還是列印了1。

解釋了這個問題,那麼就繼續說為什麼呼叫return會崩潰,子程序返回時修改了ebp,exp兩個暫存器,然後將main函式返回,當父程序執行完return 0時,兩個暫存器已經被子程序修改了,而main()函式是被其他函式呼叫的,父程序的東西被你子程序修改了,所以報出了段錯誤。

我將main函式最後的return 0 換成exit(0)是不會報錯的,因為exit並不會去釋放棧幀。

以上就是我關於vfork函式的一些理解。

由於當前的fork()函式具有寫實拷貝的機制,所以,盡量可以不使用vfork()就別使用它,因為你一旦使用,你就得時刻提防子程序對父程序的影響。

如果使用的話,切記讓子程序直接exec程式替換,並且exit返回。

程序的控制:

linux fork函式與vfork函式

一 fork 1.呼叫方法 include include pid t fork void 正確返回 在父程序中返回子程序的程序號,在子程序中返回0 錯誤返回 1 子程序是父程序的乙個拷貝。即,子程序從父程序得到了資料段和堆疊段的拷貝,這些需要分配新的記憶體 而對於唯讀的 段,通常使用共享記憶體的方...

程序管理中vfork函式

vfork函式的呼叫和返回值與fork函式的相同,但是兩者的功能有所不同。1.fork建立的子程序會複製其父程序的資料段和堆疊段 vfork的父程序共享資料段。2.vfork並不會把父程序的位址空間完全複製給子程序,因為子程序會立刻呼叫exec或者exit,也就不會訪問該位址空間,只在子程序呼叫ex...

Linux學習之 vfork函式

為什麼使用vfork 希望父子程序執行不同的 例如 網路服務程式中,父程序等待客戶端的服務請求,當請求達到時,父程序呼叫fork,使子程序處理該次請求,而父程序繼續等待下乙個服務請求到達。vfork與fork的函式原型相同,用於建立新程序,而該新程序的目的是exec乙個新程式 執行乙個可執行的檔案 ...