在《unix環境高階程式設計》一書的第八章中,有一道課後習題如下:
回憶圖7-3典型的儲存空間布局。由於對應於每個函式呼叫的棧幀通常儲存在棧中,並在呼叫 vfork後,子程序執行在父程序的位址空間中,如果不是在main函式中而是在另乙個函式中呼叫vfork,以後子程序從該函式返回時,將會發生什麼情況?
作者rich stevens是一位大師,留下這麼一題必有其深意,於是結合《深入理解計算機系統》中的知識,寫了個程式驗證了下,受益良多。
首先回憶下程式執行的棧幀結構(見下圖):
從圖中可知,如果乙個函式呼叫用了另外乙個函式,那麼被呼叫者的棧幀則會被壓入棧頂被設定為「當前幀」,首先執行被呼叫者,執行完成後,呼叫者的棧幀被彈出程式棧,然後從「返回位址」返回到呼叫者的位址空間中。
於是猜想,如果在
main
函式中,呼叫了乙個函式
foo,則「當前幀」為
foo的棧幀,這時,若呼叫
vfork
建立乙個子程序,那麼根據
vfork
的語義,子程序不會完全複製父程序的位址空間,它會在父程序的位址空間中執行(
這也是為什麼
vfork
能保證子程序先執行,而
fork
不能保證。因為
vfork
建立的子程序是與父程序共享位址空間,為了避免競爭,所以就讓子程序先執行,而父程序後執行;而
fork
建立的子程序是父程序的副本,所以不會帶來競爭問題,誰先誰後也就無所謂了
),所以它共享的是「當前幀」的位址空間,因此當子程序返回時,只會改變
foo的資料,而不會改變
main
棧幀中的資料。
下面就來寫個程式驗證一下:
執行此程式,得到結果為(見下圖):
果然,可以看到在
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也有共享的內容,比如檔案描述符的檔案表,父子程序的沒個相同描述符共享同乙個檔案表,因此,父 子程序對同一檔案使用相同的檔案位移向量。乙個程序可以有多個子程序,但只能有乙個...