标準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