Linux學習之 fork函式

2022-08-28 18:09:08 字數 2694 閱讀 2977

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...