天天看點

标準i/o緩沖區類型詳解

标準I/O庫提供緩沖的目的是盡可能地減少使用read和write調用的次數。他也對每個I/O流自動地進行緩沖管理,進而避免了應用程式需要考慮這一點所帶來的麻煩。不幸的是,标準I/O庫最令人迷惑的也是他的緩沖。

标準I/O提供了三種類型的緩沖:

1、全緩沖。這種情況下,在填滿标準I/O緩沖區後才進行實際I/O操作。對于駐留在磁盤上的檔案通常是由标準I/O庫實施全緩沖。一個流上執行第一次I/O操作時,相關标準I/O函數通常調用malloc獲得需使用的緩沖區。

術語沖洗說明I/O緩沖區的寫操作。緩沖區可由标準I/O例程自動沖洗,或者可以調用函數fflush沖洗一個流。值得引起注意的是在UNIX環境 中,flush有兩種意思。在标準I/O庫方面,flush意味着将緩沖區中的内容寫到磁盤上。在終端驅動程式方面flush表示丢棄已存儲在緩沖區中的資料。

2、行緩沖。在這種情況下,當在輸入和輸出中遇到換行符時,标準I/O庫執行I/O操作。這允許我們一次輸出一個字元,但隻有在寫了一行之後才進行實際I/O操作。當流涉及一個終端時,通常使用行緩沖。

對于行緩沖有兩個限制。第一,因為标準I/O庫用來收集每一行的緩沖區的長度是固定的,是以隻要填滿了緩沖區,那麼即使沒有寫一個換行符,也進行I/O操 作。第二,任何時候隻要通過标準I/O庫要求從a一個布袋緩沖的流,或者b一個行緩沖的流得到輸入資料,那麼就會造成沖洗所有行緩沖輸出流。在b中帶了一 個在括号中的說明,其理由是,所需的資料可能已在緩沖區中,他并不需求在需要資料時才從核心讀資料。很明顯,從不帶緩沖的一個流中進行輸入要求當時從核心得到資料。

3、不帶緩沖。标準I/O庫不對字元進行緩沖存儲。例如,如果用I/O函數fputs寫15個字元到不帶緩沖的流中,則該函數很可能用write系統調用函數将這些字元立即寫至相關聯的打開檔案中。

标準出錯流stderr通常是不帶緩沖的,這就使得出錯資訊可以盡快顯示出來,而不管它們是否含有一個換行符。

ISO C要求下列緩沖特征:

當且僅當标準輸入和标準輸出并不涉及互動式裝置使,他們才是全緩沖的。

标準出錯絕不會使全緩沖的。

但是,這并沒有告訴我們如果标準輸入和标準輸出涉及互動式裝置時,他們是不帶緩沖的還是行緩沖的;以及标準出錯時不帶緩沖的還是行緩沖的。很多系統預設使用下列類型的緩沖:

标準出錯是不帶緩緩沖的。

如若是涉及終端裝置的其他流,則他們是行緩沖的;否則是全緩沖的。

對任何一個給定的流,如果我們并不喜歡這些系統預設的情況,則可調用下列函數中的一個更改緩沖類型:

void setbuf(FILE *restrict fp, char *restrict buf)

int setvbuf(FILE *restrict fp, char *restrict buf,int mode,size_t size)

看個小例子

源程式:

[[email protected] src]# cat simplefork.c

#include 

#include 

#include

int globa = 4;

int main (void )

{

pid_t pid;

int vari = 5;

printf ("before fork\n" );

if ((pid = fork()) < 0){

  printf ("fork error\n");

  exit (0);

}else if (pid == 0){

  globa++ ;

  vari--;

  printf("Child changed\n");

}else

  printf("Parent did not changde\n");

  printf("globa = %d vari = %d\n",globa,vari);

  exit(0);

}

執行結果:

輸出到标準輸出

[[email protected] bin]# ./simplefork

before fork

Child changed

globa = 5 vari = 4

Parent did not changde

globa = 4 vari = 5

重定向到檔案時before fork輸出兩邊

[[email protected] bin]# ./simplefork>temp

[[email protected] bin]# cat temp

before fork

Child changed

globa = 5 vari = 4

before fork

Parent did not changde

globa = 4 vari = 5

分析直接運作程式時标準輸出是行緩沖的,很快被新的一行沖掉。而重定向後,标準輸出是全緩沖的。當調用fork時before fork這行仍儲存在緩沖中,并随着資料段複制到子程序緩沖中。這樣,這一行就分别進入父子程序的輸出緩沖中,餘下的輸出就接在了這一行的後面。

原文位址:http://blog.chinaunix.net/uid-22002972-id-1805611.html

繼續閱讀