vfork建立的子程序與父程序位址空間關係

2021-06-07 18:38:19 字數 1764 閱讀 3804

在《unix環境高階程式設計》一書的第八章中,有一道課後習題如下:

回憶圖7-3典型的儲存空間布局。由於對應於每個函式呼叫的棧幀通常儲存在棧中,並在呼叫 vfork後,子程序執行在父程序的位址空間中,如果不是在main函式中而是在另乙個函式中呼叫vfork,以後子程序從該函式返回時,將會發生什麼情況?

作者rich stevens是一位大師,留下這麼一題必有其深意,於是結合《深入理解計算機系統》中的知識,寫了個程式驗證了下,受益良多。

首先回憶下程式執行的棧幀結構(見下圖):

從圖中可知,如果乙個函式呼叫用了另外乙個函式,那麼被呼叫者的棧幀則會被壓入棧頂被設定為「當前幀」,首先執行被呼叫者,執行完成後,呼叫者的棧幀被彈出程式棧,然後從「返回位址」返回到呼叫者的位址空間中。

於是猜想,如果在

main

函式中,呼叫了乙個函式

foo,則「當前幀」為

foo的棧幀,這時,若呼叫

vfork

建立乙個子程序,那麼根據

vfork

的語義,子程序不會完全複製父程序的位址空間,它會在父程序的位址空間中執行(

這也是為什麼

vfork

能保證子程序先執行,而

fork

不能保證。因為

vfork

建立的子程序是與父程序共享位址空間,為了避免競爭,所以就讓子程序先執行,而父程序後執行;而

fork

建立的子程序是父程序的副本,所以不會帶來競爭問題,誰先誰後也就無所謂了

),所以它共享的是「當前幀」的位址空間,因此當子程序返回時,只會改變

foo的資料,而不會改變

main

棧幀中的資料。

下面就來寫個程式驗證一下:

[cpp]view plain

copy

print?

#include

#include

#include

int glob = 88;               //a global var 

void foo(int); 

int main(int argc,char *arg) 

void foo(int var) 

/*parent process continues here*/ 

printf("in foo var:%d  glob:%d  loc:%d  pid:%d/n",var,glob,loc,getpid()); 

執行此程式,得到結果為(見下圖):

果然,可以看到在

foo和

main

中,程序號都是一樣的,也就說明

foo和

main

在同一程序中。但是各個變數的值卻有差異:在

foo返回後

mian

函式中的區域性變數

var依然是初始值,並沒有增加,推其原因,就是因為子程序共享的是

foo的棧幀資料,而非

main

函式的棧幀,所以自然也就不會改變

main

棧幀中的資料。

vfork

建立的子程序,共享的是父程序當前棧幀的位址空間。

vfork建立的子程序與父程序位址空間關係

在 unix環境高階程式設計 一書的第八章中,有一道課後習題如下 回憶圖7 3典型的儲存空間布局。由於對應於每個函式呼叫的棧幀通常儲存在棧中,並在呼叫 vfork後,子程序執行在父程序的位址空間中,如果不是在main函式中而是在另乙個函式中呼叫vfork,以後子程序從該函式返回時,將會發生什麼情況?...

程序的建立 fork與vfork

目錄 fork函式 fork的使用 vfork函式 fork 與 vfock 都是建立乙個程序,那它們有什麼區別呢?程序的正常終止方法?程序的異常終止 為什麼vfork 子程序中可以呼叫 exit 卻不可以呼叫exit 也不可以直接return呢?標頭檔案 include 函式原型 pid t fo...

fork和vfork與程序和子程序

fork和vfork同樣可以建立子程序,但fork會把父程序的資源做拷貝,而vfork會直接在父程序的位址空間中執行。但是fork也有共享的內容,比如檔案描述符的檔案表,父子程序的沒個相同描述符共享同乙個檔案表,因此,父 子程序對同一檔案使用相同的檔案位移向量。乙個程序可以有多個子程序,但只能有乙個...