歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux系統編程 關於SDTIO庫緩沖區

我們知道標准C中的文件讀取的函數比如printf,fwrite等函數,實際都是調用OS級別的API,比如LINUX下就是wirte,read函數,而write read函數在用戶態下是沒有緩沖的, 當然在內核態有OS CACHE/OS BUFFER,所以某些直接調用wirte,read的程序肯定會分配一個緩沖區,特別是O_DIRECT這種方式下,內核態的OS CACHE和OS BUFFER沒用
這種情況下用戶態的BUFFER顯得更加重要,因為不可能一次讀一個字節吧,那性能可想而知而作為用戶態空間的STDIO也是這樣做的,它會為打開的文件分配緩存,默認應該是8192字節

如下圖摘自UNIX系統編程手冊 13章:

實際上我們可以使用setvbuf來設置某個打開文件的緩沖大小及模式。
我們來看看原型:
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
返回0為成功,非零為失敗
FILE *stream:打開文件的FILE*
 char *buf:BUFFER的地址,如果為NULL,MODE為_IOLBF和_IOFBF則自動分配緩沖區
          如果為_IONBF則不分配緩沖區
int mode:_IONBF不使用緩沖區,立即調用write/read,忽略buf和size為NULL和0,stderr屬於這個
          _IOLBF使用行緩沖I/O,終端設備默認為這種。要麼遇到換行符要麼緩沖滿才調用write/read,          stdin/stdout屬於這個。
          _IOFBF采用全緩沖I/O,buffer滿才調用write/read,磁盤I/O屬於這個比如fwrite/fread
 size_t size:緩沖大小

更簡單函數setbuf原型如下:
void setbuf(FILE *stream, char *buf);
相當於
setvbuf(fp,buf,(buf !=NULL)?_IOFBF:_IONBF,BUFSIZ);

如果buf=NULL則_IONBF打開不帶緩沖,或者調用全緩沖,BUFSIZ默認8192。
所以我們如果不想用緩沖直接:
setvbuf(fp,NULL)
即可。

現在回想一下fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

fread的時候我們通常要calloc一塊內存用於void *ptr,那麼現在我們想一下實際
上這個數據正常緩存到了3個地方
1、用戶分配的內存*ptr
2、STDIO的緩存默認8192
3、內核態OS CACHE
這視乎有點臃腫,我們可以想辦法簡化。事實上數據庫軟件有時候只使用了用戶態的一份緩存,而打開O_DIRECT來提高性能。

下面一個小程序可以驗證打開和關閉stdout緩沖的區別:

int main(void)
 {
        int i;
 //      setbuf(stdout,NULL);


        for(i=0;i<10;i++)
        {
                printf("-");
                sleep(1);
        }


        printf("\n");
 }

區別就是是否使用setbuf,如果使用setbuf則 -符號會一個一個輸出,不使用會一起輸出
這就是STDIO緩存在作怪。

Copyright © Linux教程網 All Rights Reserved