程序建立fork 和vfork

2021-08-13 11:21:01 字數 2827 閱讀 8571

乙個現有的程序可以通過兩種方式建立乙個新的程序,下面詳細介紹兩種fork()vfork()

函式原型( man 手冊):

#include 

pid_t fork(void);

描述:fork()以當前的程序為副本建立乙個新的程序,新建立的程序被稱為子程序, 當前的程序被稱為父程序,父程序和子程序執行在各自的位址空間。

返回值:

在父程序中返回子程序 的pid,子程序中返回0。可以這樣理解,對於父程序來說它可以有多個子程序,所以父程序需要知道子程序的 pid , 而對於子程序來說,它只有乙個父親,而且其父程序 ppid 已經記錄在它的pcb中了,所以就沒必要再返回父程序 pid 了。而fork失敗的話返回-1。

fork失敗原因:

用法例項:

#include 

#include

#include

#include

#include

int main()

else

if(ret > 0)else

printf("%d come here\n", getpid());

return

0;

}

執行結果

從**中看,我們讓父程序睡眠三秒(三秒並不保證子程序能執行完),以保證讓子程序先執行,3 秒後父程序開始執行,列印結果如我們所料。

下面看看系統呼叫 fork 的原理。

在執行fork函式後,核心將拷貝乙份父程序的副本作為子程序。子程序獲得父程序的資料空間,堆和棧、檔案描述符表(這通常在網路服務中使用,即父子程序各自關閉自己不需要的檔案描述,這樣就不會對對方造成影響)…的副本,但是父子程序共享正文段,即**段。所以fork之後,父子程序仍然執行的是同乙份**,但我們根據返回值得不同,可以讓它們執行不同的邏輯,如上圖所示,在fork之後父子程序各自執行灰色部分**,從上面執行結果中也可以看出 (注意!這只是讓它們執行不同的邏輯,本質上執行的還是同乙份**)

一般情況下,被建立的子程序會呼叫程序替換函式exec,所以fork之後子程序一般就不去執行和父程序同樣的**。

父子程序除了共享**段之外,它們也共享資料段。父子程序的資料段通過頁表對映到同一塊物理記憶體中,當有一方企圖修改資料段時,便以寫時拷貝的方式 —— 先拷貝乙份要修改的資料,再通過頁表對映到新拷貝的記憶體處,這樣一方對資料的修改就不會影響另一方。如下例項:

#include 

#include

#include

#include

#include

int g_val = 0;

int main()

else

if(ret > 0)else

printf("%d come here\n", getpid());

return

0;

}

執行結果:

可以看到,父子程序對資料的修改並不會影響到對方。如下圖:

vfork函式也用來建立乙個程序,但不同於fork的是vfork出的子程序不會獲得乙份父程序的副本,而是直接在父程序的位址空間內執行,所以子程序對資料的修改會影響到父程序內。這一點將在下面驗證。這麼做的原因是:建立的子程序會立即呼叫exec程序函式替換,所以子程序不會使用父程序的位址空間。

除此之外,vfork函式會保證子程序先執行,直到子程序呼叫exitexec函式後,父程序才會被排程執行,此間,父程序一直被掛起等待子程序的執行結束。如下**:

可以看到,子程序執行完了,父程序才執行,而且子程序中對變數i的修改影響到了父程序。

——完!

程序建立函式fork與vfork

1.fork 1 函式的功能 建立乙個程序 2 函式的原型 pid t fork void 3 函式的返回值 0 出錯 0 子程序 0 父程序 其值為子程序的識別號 4 標頭檔案 include fork的奇妙之處在於它被呼叫一次,卻返回兩次,它可能有三種不同的返回值。include include...

程序建立之fork與vfork

由圖中的對映關係我們可以發現,虛擬位址與實體地址並不是一一對應的,這樣也就會出現一種問題,乙個變數位址相同內容不同,其實是虛擬位址相同,所對應的實體地址不同的原因 那麼是誰管理著虛擬位址空間呢?pcb中有mm strct管理虛擬位址空間 linux中絕大多數函式出錯返回值都是 1,函式出錯後將錯誤編...

程序的建立 fork與vfork

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