C/C++的全緩沖、行緩沖和無緩沖
1.簡介
C/C++中,基于I/O流的操作最終會調(diào)用系統(tǒng)接口read()和write()完成I/O操作。為了使程序的運行效率最高,流對象通常會提供緩沖區(qū),以減少調(diào)用系統(tǒng)I/O接口的調(diào)用次數(shù)。
緩沖方式存在三種,分別是:
(1)全緩沖。輸入或輸出緩沖區(qū)被填滿,會進行實際I/O操作。其他情況,如強制刷新、進程結(jié)束也會進行實際I/O操作。
對于讀操作來說,當讀入內(nèi)容的字節(jié)數(shù)等于緩沖區(qū)大小或者文件已經(jīng)到達結(jié)尾,或者強制刷新,會進行實際的I/O操作,將外存文件內(nèi)容讀入緩沖區(qū);對于寫操作來說,當緩沖區(qū)被填滿或者強制刷新,會進行實際的I/O操作,緩沖區(qū)內(nèi)容寫到外存文件中。磁盤文件操作通常是全緩沖的。
(2)行緩沖。輸入或輸出緩沖區(qū)遇到換行符會進行實際I/O操作。其他與全緩沖相同。
(3)無緩沖。沒有緩沖區(qū),數(shù)據(jù)會立即讀入內(nèi)存或者輸出到外存文件和設(shè)備上。標準錯誤輸出stderr是無緩沖的,這樣能夠保證錯誤信息及時反饋給用戶,供用戶排除錯誤。
三種緩沖類型的宏定義在頭文件<stdio.h>
。
緩沖類型 | 宏 |
全緩沖 | _IOFBF |
行緩沖 | _IOLBF |
無緩沖 | _IONBF |
Linux環(huán)境下,下面一段代碼可以很好地體現(xiàn)全緩沖和行緩沖的區(qū)別。
#include <stdio.h> #include <stdlib.h> int glob=6; int main(int argc, char** argv) { int var; pid_t pid; printf("a write to stdout\n"); if(pid=fork()<0) { printf("fork error"); } else { if(pid==0) { glob++; var++; } else { sleep(2); } } printf("pid=%d,glob=%d,var=%d\n",getpid(),glob,var); exit(0); }
編譯成功后默認生成a.out,運行結(jié)果如下:
./a.out
a write to stdout
pid=4823,glob=7,var=4195873
pid=4824,glob=7,var=4195873./a.out > temp.txt
cat temp.txt
a write to stdout
pid=4864,glob=7,var=4195873
a write to stdout
pid=4865,glob=7,var=4195873
可見printf在輸出到標準輸出(顯示器)時,是行緩沖,遇到換行符時會將緩沖區(qū)內(nèi)容輸出到顯示器,并清空緩沖區(qū)。當使用重定向命令時,標準輸出被重定向到磁盤文件,此時標準輸出變成全緩沖,遇到換行符不輸出,而是被拷貝至子進程中,在父子進程結(jié)束后,各有一份輸出。
2.緩沖區(qū)的設(shè)置
(1)緩沖打開或關(guān)閉,可使用函數(shù)setbuf()或者setbuffer()。參數(shù)buf指向緩沖區(qū),表示開啟緩沖,通常是全緩沖。將buf參數(shù)設(shè)置為NULL,表示關(guān)閉緩沖。注意,setbuffer()是非C標準庫函數(shù),常見于Linux。
setbuf()的緩沖區(qū)長度至少為BUFSIZ(定義在stdio.h),否則可能會出現(xiàn)緩沖區(qū)溢出。setbuffer可以指定緩沖區(qū)大小。
//@header:stdio.h //@brief:設(shè)置指定的緩沖區(qū)或關(guān)閉緩沖 //@param:stream:文件指針;buffer:緩沖區(qū)地址 //@notice:使用默認緩沖大小BUFSIZ(在stdio.h中定義) void setbuf ( FILE * stream, char * buffer ); //@notice:同setbuf,但可指定緩沖區(qū)大小 void setbuffer(FILE *stream, char *buf, size_t size);
將buffer指定為NULL,關(guān)閉標準輸出緩沖。
setbuf(stdout,NULL)
指定新的緩沖區(qū)。
static char newBuffer[BUFSIZ];//至少是BUFSIZ(定義在stdio.h),否則存在緩沖溢出可能 setbuf(stdout,(char*)&newBuffer); //或者指定緩沖區(qū)大小 static char newBuffer[512]; setbuffer(stdout,(char*)&newBuffer,512);
(2)更改緩沖模式,可使用函數(shù)setvbuf()。
//@header:stdio.h //@brief:更改緩沖模式并設(shè)置緩沖區(qū) //@param:stream:文件指針;buf緩沖區(qū)地址;type:緩沖區(qū)模式;size:緩沖區(qū)大小 //@ret:0成功,非0失敗 int setvbuf(FILE *stream, char *buf, int type, unsigned size);
例如,將流緩沖區(qū)設(shè)置為行緩沖,調(diào)用setvbuf()時,緩沖區(qū)地址設(shè)為NULL,緩沖區(qū)大小設(shè)為0。注意,前提是存在緩沖區(qū)。
setvbuf(stream,NULL,_IOLBF,0); //將緩沖改為行緩沖 //上面的代碼等價于 setlinebuf(stream); //for Linux
如果調(diào)用setvbuf指定了緩沖區(qū)大小size大于0,緩沖區(qū)buf為NULL,則交由setvbuf進行malloc申請緩沖區(qū)。
//間接申請1024字節(jié)全緩沖區(qū) setvbuf(stream,NULL,_IOFBF,1024);
以上就是C/C++的全緩沖、行緩沖和無緩沖的詳細內(nèi)容,更多關(guān)于C/C++ 緩沖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++數(shù)據(jù)結(jié)構(gòu)之并查集詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之并查集詳解,并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),用于處理一些不相交集合的合并及查詢問題,并查集的思想是用一個數(shù)組表示了整片森林,需要的朋友可以參考下2023-08-08