題目:請問下面的程式一共輸出多少個「-」?
#include #include如果你對 fork ()的機制比較熟悉的話,這個題並不難,輸出應該是 6 個「-」,但是,實際上這個程式會很 tricky 地輸出 8 個「-」。#include
int main (void)
return0;
}
要講清這個題,我們首先需要知道 fork ()系統呼叫的特性,
所以,上面的那個程式為什麼會輸入 8 個「-」,這是因為 printf (「-」);語句有 buffer,所以,對於上述程式,printf (「-」);把「-」放到了快取中,並沒有真正的輸出(參看《c語言的迷題》中的第一題),在 fork 的時候,快取被複製到了子程序空間,所以,就多了兩個,就成了 8 個,而不是 6 個。
另外,多說一下,我們知道,unix 下的裝置有「塊裝置」和「字元裝置」的概念,所謂塊裝置,就是以一塊一塊的資料訪問的裝置,字元裝置是一次訪問乙個字元的裝置。磁碟、記憶體都是塊裝置,字元裝置如鍵盤和串列埠。塊裝置一般都有快取,而字元裝置一般都沒有快取。
對於上面的問題,我們如果修改一下上面的 printf 的那條語句為:
printf ("或是-\n");
printf ("就沒有問題了(就是 6 個「-」了),因為程式遇到「\n」,或是 eof,或是緩中區滿,或是檔案描述符關閉,或是主動 flush,或是程式退出,就會把資料刷出緩衝區。需要注意的是,標準輸出是行緩衝,所以遇到「\n」的時候會刷出緩衝區,但對於磁碟這個塊裝置來說,「\n」並不會引起緩衝區刷出的動作,那是全緩衝,你可以使用 setvbuf 來設定緩衝區大小,或是用 fflush 刷快取。-");
fflush (stdout);
我估計有些朋友可能對於 fork ()還不是很了解,那麼我們把上面的程式改成下面這樣:
注意:下面的 printf 有「\n」
printf ("
ppid=%d, pid=%d, i=%d \n
", getppid (), getpid (), i);
}sleep (10); //
讓程序停留十秒,這樣我們可以用 pstree 檢視一下程序樹
return0;}
於是,上面這段程式會輸出下面的結果,(注:編譯出的可執行的程式名為 fork)
ppid=8858, pid=8518, i=0面對這樣的圖你可能還是看不懂,沒事,我好事做到底,畫個圖給你看看:ppid=8858, pid=8518, i=1
ppid=8518, pid=8519, i=0
ppid=8518, pid=8519, i=1
ppid=8518, pid=8520, i=1
ppid=8519, pid=8521, i=1
$ pstree -p | grep fork
|-bash (8858)-+-fork (8518)-+-fork (8519)---fork (8521)
| | `-fork (8520)
注意:上圖中的我用了幾個色彩,相同顏色的是同乙個程序。於是,我們的 pstree 的圖示就可以成為下面這個樣子:(下圖中的顏色與上圖對應)
這樣,對於 printf (「-」);這個語句,我們就可以很清楚的知道,哪個子程序複製了父程序標準輸出緩中區里的的內容,而導致了多次輸出了。(如下圖所示,就是我陰影並雙邊框了那兩個子程序)
現在你明白了吧。(另,對於圖中的我本人拙劣的配色,請見諒!)
Linux下的fork 函式
fork fork的英文翻譯是 分叉 同樣在linux中我們也可以理解為如果使用了fork 函式,程序也會 分叉 下面進行具體的說明fork 函式。定義 通過系統呼叫建立乙個與原程序幾乎完全相同的程序,其中新產生的程序成為子程序。原型 pid t fork void fid t相當於int型別特殊之...
linux下fork的使用
需要包含標頭檔案 include include 函式宣告 pid t fork void 其中pid t在sys types.h中定義 typedef pid t pid t 可以看到只是乙個int.fork 通過複製呼叫過程來建立乙個新過程。新程序稱為子程序,與呼叫程序 稱為父程序 完全相同,但...
Linux下fork函式的使用
fork函式每呼叫一次,函式返回兩次,新程序 子程序 中返回0,原程序 父程序 中返回子程序的pid。q 為什麼不是子程序中返回父程序pid,父程序中返回0呢?那是因為乙個父程序有很多子程序,如果不返回其特定子程序的pid,之後需要呼叫其子程序時就找不到這個子程序了 而乙個子程序只有乙個父程序,如果...