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

當調(diào)用write寫數(shù)據(jù)的時候,調(diào)用完成后write直接返回,但是磁盤是個慢速設(shè)備,操作系統(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)槿彺?,在某些情況下可能會導(dǎo)致一些非預(yù)期錯誤,比如調(diào)用printf(“*****\n”)時,當以交互方式運行該程序時,會正常輸出。但是當將標準輸出重新定向到一個文件時,緩沖區(qū)區(qū)變?yōu)槿彺?,printf就不會正常輸出,該行數(shù)據(jù)仍在緩沖區(qū)中。如果此時再fork一個子進程,數(shù)據(jù)空間被復(fù)制到子進程中時,該緩沖區(qū)數(shù)據(jù)也被復(fù)制到子進程中。接著在子進程中如果輸出則會刷新之前在緩沖區(qū)的內(nèi)容,產(chǎn)生一些非預(yù)期的輸出。

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

延伸閱讀

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