nfork函式建立乙個新程序,新程序被稱為子程序
n函式原型:pid_t fork(void)
n返回值:
fork函式呼叫一次,但是返回兩次:在子程序中返回0,在父程序中返回子程序id,出
錯返回-1。通過返回值,可以確定是在父程序還是子程序中。
n子程序和父程序繼續執行fork呼叫之後的指令。
子程序是父程序的副本:
1.子程序獲得父程序資料空間、堆和棧的副本;父子程序並不共享這些儲存空間。
2.父子程序共享正文段(唯讀的);
3.為了提高效率,fork後並不立即複製父程序空間,採用了cow(copy-on-write)
;當父子程序任意之一,要修改資料段、堆、棧時,
進行複製操作,但僅複製修改區域;
看乙個程式:
#include#include
#include
using
namespace std;
int glob = 6;
char buf = "
a write to stdout\n
";int main(void)
printf("
before fork\n
");
if ( (pid = fork()) < 0)
else
if (pid == 0)
else
printf("
pid = %d, glob = %d, var = %d\n
", getpid(), glob, var);
return
0;}
直接輸出到控制台:
a write to stdout
before fork
pid = 1867, glob = 7, var = 89
pid = 1866, glob = 6, var = 88
使用重定向「./a.out>a.txt」,a.txt內容如下:
a write to stdout
before fork
pid = 1939, glob = 7, var = 89
before fork
pid = 1938, glob = 6, var = 88
為什會有這個差別?
先來看下「stdout_fileno」和「file *stdout」的區別:
stdin / stdout / stderr是file*型別,供標準c++一級提供的檔案操作函式庫使用,定義在標頭檔案中。
stdin_fileno / stdout_fileno / stderr_fileno 是int型別,其實質是檔案描述符(值分別為0,1,2),定義在標頭檔案中。
file * stdin / stdout / stderr 對應的檔案描述符(fd)分別是 stdin_fileno(0) / stdout_fileno(1) / stderr_fileno(2) 。
兩者的差別主要是標準i/o是帶緩衝(具體見下面說明)的,而stdin_fileno / stdout_fileno / stderr_fileno是不帶緩衝的。
我們只需記住:
使用stdin / stdout / stderr的函式主要有:fread、fwrite、fclose等,基本上都以f開頭。
使用stdin_fileno / stdout_fileno / stderr_fileno的函式有:read、write、close等。
關於兩者更詳細的說明:
1.「file *stdout 和 stdout_fileno 的區別」(
2."對stdin,stdout 和stdout_fileno,stdin_fileno的學習"(
下面看下關於"printf"/"write"和緩衝的說明:
printf是在stdio.h中宣告的函式,而標準io都是帶緩衝的,所以printf是帶緩衝的。而write則是不帶緩衝的。
標準io在輸入或輸出到終端裝置時,它們是行緩衝的,否則(檔案)它們是全緩衝的。而標準錯誤流stderr是不使用緩衝的。更為準確的描述是:當且僅當標準輸入和標準輸出並不涉及互動式裝置使,他們才是全緩衝的。標準出錯流不使用緩衝。
下列情況會引發緩衝區的重新整理(清空緩衝區):
1、緩衝區滿時;
2、執行flush語句;
3、執行endl語句(printf是"\n");
4、關閉檔案。
綜上所述,write的內容在父程序直接輸出到了裝置,「before fork」在主線程輸出到終端後因為換行符而清空了緩衝區,所以也只輸出了一次。
而重定向到"a.txt"時,printf使用的是全緩衝,所以「before fork」並未輸出到裝置,而是隨著fork()而被複製了乙份到子程序的空間中,所以輸出了兩次。
注意:在重定向父程序輸出時,子程序也被重定向了。
為什麼父程序要等待2秒?
在fork時,父程序所有開啟的檔案描述符都被複製乙份到子程序中,然而他們共享檔案描述符所指向的檔案物件(file結構:描述檔案讀寫指標,偏移量,標誌等)。如果不等待,檔案偏移量被交替修改,很可能產生混亂的輸出。
Linux學習之「fork函式」
n返回值 fork函式呼叫一次,但是返回兩次 在子程序中返回0,在父程序中返回子程序id,出錯返回 1。通過返回值,可以確定是在父程序還是子程序中。n子程序和父程序繼續執行fork呼叫之後的指令。子程序是父程序的副本 1.子程序獲得父程序資料空間 堆和棧的副本 父子程序並不共享這些儲存空間。2.父子...
研究linux函式 之 fork()
程序可以看做程式的一次執行過程,在linux下每個程序有唯一的pid來標識程序。特殊程序 id為0的是排程程序,該程序是核心的一部分,不執行任何磁碟上的程式 id為1的是init程序,init通常讀取與系統有關的初始化檔案 etc rc 檔案 etc inittab檔案 etc init.d 中的檔...
linux學習 fork用法
linux當中可以使用fork函式建立乙個新程序 include pid t fork void 返回值 子程序中返回0,父程序中返回子程序id,出錯返回 1 在fork呼叫之後,子程序和父程序繼續執行fork呼叫之後的指令。子程序獲得父程序資料空間 堆和棧的副本,但是並不共享這些儲存空間部分。fo...