Linux 系統中調用 exit() 和 _exit() 結束進程的區別是什麼?

網上搜索到一些博客有對這兩個函數的解釋,看了之後還是犯迷糊。

exit()函數定義在stdlib.h頭文件中,_exit()定義在unistd.h頭文件中,這是區別之一。

調用_exit()函數時,其會關閉調用進程的所有文件描述符,清理內存和內核數據,但不會刷新流(stdin, stdout, stderr ...)。

exit()函數是在_exit()函數之上的一個封裝,其會調用_exit(),並在調用之前先刷新流,並且exit()系統調用之前要檢查文件的打開情況,把文件緩衝區的內容寫迴文件。所以要保證數據的完整性,得調用exit()函數。

但是也查到一些解釋,《Linux環境C程序設計》(第二版 徐誠等編著)一書第205頁exit系統調用小節中有這樣描述:「由fork()函數創建的子進程分支里,正常情況下使用函數exit()是不正確的,這是因為使用它會導致標準輸入輸出的緩衝區被清空兩次,而且臨時文件可能被意外刪除。」這與上面的解釋相悖了,究竟誰是對的?

基於上面的描述,我還有以下疑問:

1、刷新緩衝區是簡單的刪除其中的數據,還是要進行一些操作,例如保存數據再清空?

2、exit()為什麼會導致標準輸入輸出的緩衝區被清空兩次?

希望有高手不吝賜教,解釋exit()和_exit()的區別及使用方法。

謝謝!


基本來說,_Exit(或 _exit,建議使用大寫版本)是為 fork 之後的子進程準備的特殊 API。功能見 [1],討論見 [2]。

因為在 fork 之後,exec 之前,很多資源還是共享的(如某些文件描述符),如果使用 exit 會關閉這些資源,導致某些非預期的副作用(如刪除臨時文件等)。

「刷新」是對應 flush,意思是把內容從內存緩存寫出到文件里,而不僅僅是清空(所以常見的對 stdin 調用 flush 的方法是耍流氓而已)。如果在 fork 的時候父進程內存有緩衝內容,則這個緩衝會帶到子進程,並且兩個進程會分別 flush (寫出)一次,造成數據重複。[3]

[1] POSIX 標準:_Exit

[]2 c - how to exit a child process

[3] c - How does fork() work with buffered streams like stdout?


推薦閱讀:

TAG:編程 | Linux | Linux系統管理 |