大家有興趣可以想想,下面輸出了多少個「g」?
#include #include #include int main(void)
wait(null);
wait(null);
return 0;
}
也許你很快就說,那麼簡單,第一次迴圈,fork後2個程序,第二次再fork出4個,一共6個程序,肯定是6個「g」
恭喜你,如果我是面試官,那麼你已經跪了 = =
答案:會輸出8個「g」
有乙個很重要的東西是,在fork()的呼叫處,整個父程序空間會原模原樣地複製到子程序中,包括指令,變數值,程式呼叫棧,環境變數,緩衝區,等等。
等等!!什麼,你說全部複製過去?那麼我可以解釋為:
上面的那個程式為什麼會輸入8個「-」,這是因為printf(「-「);語句有buffer
我們來試試printf的緩衝區:
#include #include //for sleep()
int main(void)
return 1;
}
哦哦!!如果不做fflush這個動作,上邊的輸出便不會顯示到螢幕上咯?
除非其中有換行操作或者緩衝區,這也許就是所謂的「到終端行規程」!
呃呃,不要脫離了重點,我們還是回到剛才的fork問題上~
既然我們知道了printf有緩衝區,那麼,又如何?
容我引用下酷殼大神美麗的**:
你可以清楚的看到,用陰影框標註出來的兩個「最終版子程序(i=2)」
他們在fork拷貝的時候,就將 parent的緩衝區一併拷貝過去,這時「g」還在緩衝區
那麼,在輸出的時候,兩個子程序才一併把「g」從緩衝區輸出來,那麼是不是兩個子程序沒人多輸出了乙個?
1+1+1+1+12+12=8個
ok,我知道你和我一樣可能有點懵懵的,我改下程式咯~
#include #include #include int main(void)
wait(null);
wait(null);
return 0;
你可以gcc下這個程式,在我的電腦裡輸出是這樣的:
g ppid=3082, pid=3128, i=0 g ppid=3128, pid=3130, i=1
g ppid=3128, pid=3129, i=0 g ppid=3129, pid=3131, i=1
g ppid=3128, pid=3129, i=0 g ppid=3128, pid=3129, i=1
g ppid=3082, pid=3128, i=0 g ppid=3082, pid=3128, i=1
可以看到ppid為3082 pid為3128的輸出有3次
同樣的,ppid為3128 pid為3129的輸出有3次
你將顯然發現,原本i=0時應該只會有兩個「g」被輸出,但是現在居然詭異地多出了兩個?到底是哪兩個呢?
我索性標註下這個輸出結果吧~
(1)g ppid=3082, pid=3128, i=0 (5)g ppid=3128, pid=3130, i=1
(2)g ppid=3128, pid=3129, i=0 (6)g ppid=3129, pid=3131, i=1
(3)g ppid=3128, pid=3129, i=0 (7)g ppid=3128, pid=3129, i=1
(4)g ppid=3082, pid=3128, i=0 (8)g ppid=3082, pid=3128, i=1
明顯的,(1)和(4)是「不可能」有兩個的,(2)和(3)也是,現在你知道了吧,i=0時的兩個程序,在下一次fork的時候各自成為了下乙個父程序,在這一次fork時,他們的資訊被完全複製到了子程序,那麼最後一步每乙個子程序緩衝區裡還存有多餘的「g」(見上圖)
你還可以用pstree -p | grep fork命令試下
可以得出乙個樹狀的結構:
$ pstree -p | grep fork
|-bash(3082)-+-fork(3128)-+-fork(3129)---fork(3131)
| | `-fork(3130)
那麼,最後我們再試試,在printf乙個g的後面加上乙個換行符(或者fflush)
#include #include #include int main(void)
wait(null);
wait(null);
return 0;
}
輸出的結果將是換行的6個「g
原因就在於,每一次換行,緩衝區的「g」,就會把資料「刷」出緩衝區
(其實或是eof,或是緩中區滿,或是檔案描述符關閉,或是主動flush,或是程式退出)
yield 乙個很有趣的關鍵字
在偶然的機會下發現了這個關鍵字yield,它的作用是在乙個迴圈體 例如 foreach,for 內部 與return 一起做輸出.要注意的是yield return 所在函式的返回值為ienumerable介面型別 下面實現的是從一堆資料中找出大於特定數字的結果集。namespace test fo...
防止可重入 乙個有趣的類和乙個很有用的巨集!
這幾天在研究todolist 原始碼,看到一簡短的類,很很有意思,現把原始碼列下,並附上簡短說明 注 重入即表示重複進入,首先它意味著這個函式可以被中斷,其次意味著它除了使用自己棧上的變數以外不依賴於任何環境 包括static 這樣的函式就是 purecode 純 可重入,可以允許有該函式的多個副本...
乙個fork的面試題
題目 請問下面的程式一共輸出多少個 include inlcude int main return 0 可能開始的時候大家都以為會輸出6個 但是結果輸出了8個 要弄明白這個題,還是先從fork 呼叫開始 1 fork 系統呼叫是unix下以自身程序建立子程序的系統呼叫,一次呼叫,兩次返回,如果返回時...