建立乙個新程序的方法只有由某個已存在的程序呼叫fork()或vfork()
1.fork()函式
返回值:成功:父程序:返回子程序的pid
子程序:返回0
失敗:父程序返回-1
子程序是父程序的乙個拷貝。即子程序從父程序得到資料段和堆、棧段的拷貝,這些需要分配新的記憶體(不是與父程序共享,而是單獨分配記憶體);而對於唯讀的**段,通常使用共享記憶體的方式訪問。
fork返回後,子程序和父程序都從呼叫fork函式的下一條語句開始執行。
由於子程序與父程序的執行是無關的,所以,父程序可先於子程序執行,子程序也可以先於父程序執行
執行結果
以前的fork建立乙個子程序時,將會建立乙個新的位址空間,並且拷貝父程序的資源,然後將會有兩種行為:1.執行從父程序那裡拷貝過來的**段(程序希望複製自身,從而父子程序能同時執行不同段的**);2. 呼叫exec執行乙個新的**段(程序想執行另外乙個程式)
當程序呼叫exec時,乙個程序替換了當前程序的文字、資料、棧、堆段。這樣,前面的拷貝工作就白費力氣了,這種情況下,人們想出了vfork。
vfork並不複製父程序的程序環境,子程序在父程序的位址空間中執行,所以子程序不能進行寫操作,並且兒子「霸佔」著父親的房子的時候,就要委屈父親一下,讓他在外面歇著(阻塞),一旦兒子執行了exec或者exit後,相當於兒子買了屬於自己的房子,這時候就相當於分家了
2.vfork()函式
vfork建立新程序的主要目的在於呼叫exec函式執行另外的乙個新程式,在沒呼叫exec或exit之前,子程序的執行是與父程序共享資料段的。
vfork呼叫中,子程序先執行,父程序掛起,直到子程序呼叫exec或者exit,在這以後,父子程序的執行順序不再被限制。
執行結果
乙個經典的例子
執行結果
程式在後續執行時出現了錯誤,並且可知道是在父程序中出現的錯誤
vfork函式呼叫時,子程序比父程序先執行,在呼叫test()函式執行時,子程序執行完之後,將清理test函式的棧空間,然後子程序再呼叫fun()函式,將覆蓋掉test的棧空間,繼續執行fun函式。但是,當子程序退出後,執行父程序,但是,在test函式返回的時候該棧空間已經被子程序破壞了,不存在了,所以就出現了棧錯誤
區別:
1.vfork保證子程序先執行,在它呼叫exec或者exit之後,父程序才可能被排程執行,之後,父子程序的執行順序才不再有限制。如果在呼叫exec或者exit之前,子程序依賴於父程序的進一步動作,則會導致死鎖
2.fork要拷貝父程序的程序環境(資料段),而vfork不需要完全拷貝父程序的程序環境(資料段),在呼叫exec或者exit之前,父子程序共享程序環境(資料段),相當於執行緒概念,此時父程序阻塞等待(因為子程序先執行)。
結束子程序:
exit和_exit函式用於正常終止乙個程式,_exit()立即進入核心,exit()則需要先執行一些清除處理(包括呼叫執行各終止處理程式,關閉所有標準i/o流等),然後再進入核心。
結束子程序不用exit(0),而使用_exit(0)。因為_exit(0)在結束程序時,不對標準i/o流進行任何操作,而exit(0)回關閉程序的所有標準i/o流
本文出自 「追尋內心的聲音」 部落格,請務必保留此出處
linux程序建立之fork與vfork
乙個現有的程序可以呼叫fork函式建立乙個新的程序。原函式如下 name fork create a child process synopsis include include pid t fork void 返回值 子程序返回0,父程序返回子程序的id,出錯返回 1。測試 如下 include ...
研究linux函式 之 fork()
程序可以看做程式的一次執行過程,在linux下每個程序有唯一的pid來標識程序。特殊程序 id為0的是排程程序,該程序是核心的一部分,不執行任何磁碟上的程式 id為1的是init程序,init通常讀取與系統有關的初始化檔案 etc rc 檔案 etc inittab檔案 etc init.d 中的檔...
Linux學習之 fork函式
nfork函式建立乙個新程序,新程序被稱為子程序 n函式原型 pid t fork void n返回值 fork函式呼叫一次,但是返回兩次 在子程序中返回0,在父程序中返回子程序id,出 錯返回 1。通過返回值,可以確定是在父程序還是子程序中。n子程序和父程序繼續執行fork呼叫之後的指令。子程序是...