Linux系統(tǒng)IO中write原型為  ssize_t write(int  filedes, const void * buff, size_t nbytes) ;

當調(diào)用write寫數(shù)據(jù)的時候,調(diào)用完成后write直接返回,但是磁盤是個慢速設備,操作系統(tǒng)會將數(shù)據(jù)保存在內(nèi)核中的緩沖區(qū)中,并負責異步地將數(shù)據(jù)寫至磁盤。當然如果此時系統(tǒng)宕機了則會丟失數(shù)據(jù)。write是系統(tǒng)調(diào)用,每次調(diào)用都會陷入內(nèi)核,所以選取一個合適的塊長度buffsize,并盡量減少它的調(diào)用可以優(yōu)化效率。在ANSI C的標準IO中我們調(diào)用printf/fprintf/fputs等會以流的方式進行處理,我們只需要寫入流中,而不用像write一樣選擇一個buffsize,因為標準IO庫幫我們處理了很多細節(jié),例如緩沖區(qū)分配,以優(yōu)化長度執(zhí)行IO等。這樣的話就會減少wirte/read系統(tǒng)調(diào)用的數(shù)量,提高效率。但是與此同時會引入另外一個問題:數(shù)據(jù)拷貝,例如當使用函數(shù)fgets和fputs時,通常需要經(jīng)過兩次緩沖區(qū):一次是標準IO緩沖區(qū),還有一次是調(diào)用read和write的內(nèi)核緩沖區(qū)。但是總的來說使用標準IO相對于系統(tǒng)IO來說接口簡單,且效率相當。

標準IO提供了三種類型的緩沖區(qū):全緩存,行緩存和不帶緩存,全緩存只有在緩沖區(qū)滿時才會主動flush,通常用在對一個磁盤文件IO。行緩存在緩沖區(qū)中遇到換行符就會flush,還有一種情況是需要從標準輸入輸出得到輸入數(shù)據(jù)時也會flush緩沖區(qū),行緩存一般用在交互的終端中。不帶緩存則相當于直接 write系統(tǒng)調(diào)用輸出,標準出錯流stderr通常是不帶緩存的,這就使得出錯信息可以盡快顯示出來。除了默認的flush條件外,顯式調(diào)用fflush函數(shù)和程序正常終止時也會flush緩沖區(qū)。我們可以使用setbuf/setvbuf來更改默認的緩沖區(qū)長度,參見APUE 5.4節(jié)。

在使用標準IO的程序中,當我們將一個標準輸出重新定向到一個文件時,會將行緩存變?yōu)槿彺?,在某些情況下可能會導致一些非預期錯誤,比如調(diào)用printf(“*****\n”)時,當以交互方式運行該程序時,會正常輸出。但是當將標準輸出重新定向到一個文件時,緩沖區(qū)區(qū)變?yōu)槿彺?,printf就不會正常輸出,該行數(shù)據(jù)仍在緩沖區(qū)中。如果此時再fork一個子進程,數(shù)據(jù)空間被復制到子進程中時,該緩沖區(qū)數(shù)據(jù)也被復制到子進程中。接著在子進程中如果輸出則會刷新之前在緩沖區(qū)的內(nèi)容,產(chǎn)生一些非預期的輸出。

在網(wǎng)絡編程中,應該直接使用系統(tǒng)IO,標準IO為提升性能而引入緩沖機制增加了網(wǎng)絡應用程序的復雜性。并且,某種意義上說標準IO流是全雙工的,能同時執(zhí)行輸入和輸出,然而對流的限制和對套接字的限制,有時候會互相沖突。(參見CSAPP P611)

延伸閱讀

學習是年輕人改變自己的最好方式-Java培訓,做最負責任的教育,學習改變命運,軟件學習,再就業(yè),大學生如何就業(yè),幫大學生找到好工作,lphotoshop培訓,電腦培訓,電腦維修培訓,移動軟件開發(fā)培訓,網(wǎng)站設計培訓,網(wǎng)站建設培訓學習是年輕人改變自己的最好方式