高級I/O函數
在Linux標準庫中,有一套稱爲高級I/O函數,例如我們所熟知的printf,fopen,fread,fwrite都在此列,他們也被稱爲緩衝I/O。其特徵是對應每一個打開的文件,都存在一個緩衝區,在每次讀文件時會多讀若干條記錄,這樣下次讀文件時就可以直接從內存的緩衝區去讀。在每次寫文件時也會先寫入緩衝區,當緩衝區寫滿,或者我們手動的刷新緩衝區,或者遇到\n,EOF這樣的結束符,纔會把對應的數據從緩衝區寫入到文件中。這樣的好處是大大增加的文件的讀寫的速度,因爲我們都知道磁盤上的讀寫速度是很慢的,但這也爲我們編程帶來了一點麻煩,例如有些數據,我們認爲已經寫入了文件,但實際上它們很可能存在在緩衝區中。
關於printf的緩衝區問題推薦大家看下面的博客:
http://blog.csdn.net/bit_clearoff/article/details/53998476
exit和exit
首先我們來看看下面的實例:
從圖片中我們可以看出,通過exit(0)來結束掉main函數的程序可以輸出結果,通過調用_exit(0)函數的程序不能輸出結果。
這時爲什麼呢????
我們來看看exit()和_exit()各組定義在哪個頭文件中吧:
_exit定義在unistd.h中的第273行:
而exit()定義在stdlib.h文件中:
exit函數:定義在C標準庫stdlib.h中;當我們調用exit(0)時,表示正常退出當前進程,當我們調用eixt(1)時表示非正常退出當前進程。
具體可以查看stdlib.h文件中的宏定義:
其中exit在結束進程之前要做以下的事情:
調用atexit()註冊的函數(出口函數)
atexit()函數定義在stdlib中,它的函數定義爲:int atexit(void (*)(void)),形參爲一個返回值爲void,參數爲void的函數指針,很多時候我們需要在程序退出的時候做一些諸如釋放資源的操作,但程序退出的方式有很多種,比如main()函數運行結束、在程序的某個地方用exit()結束程序、用戶通過Ctrl+C或Ctrl+break操作來終止程序等等,因此需要有一種與程序退出方式無關的方法來進行程序退出時的必要處理。方法就是用atexit()函數來註冊程序正常終止時要被調用的函數。
在一個程序中最多可以用atexit()註冊32個處理函數,這些處理函數的調用順序與其註冊的順序相反,也即最先註冊的最後調用,最後註冊的最先調用。
我們可以使用atexit()函數在main函數結束時對整個進程的內存空間進行銷燬,作用相當於C++中的析構函數.調用cleanup()關閉所有的流
這一步操作導致所有的緩衝被輸出
最後調用_exit()函數終止進程
_exit()函數主要做了清理內存空間,結束進程調用等工作。
案例分析
這下我們應該瞭解了出現前面例子中情況的原因了,是因爲exit函數在結束進程時用cleanup()刷新了緩衝區,使緩衝區中的數據被輸出,而_exit函數只是exit函數中的一部分,它調用了系統調用函數exit().
所以eixt和_exit函數我們可以用下面這張圖來總結一下:
關於printf的緩衝區問題推薦大家看下面的博客:
http://blog.csdn.net/bit_clearoff/article/details/53998476