APUE之全緩衝 行緩衝 無緩衝

2021-07-31 03:15:59 字數 2636 閱讀 1821

基於流的操作最終會呼叫read或者write函式進行i/o操作。為了使程式的執行效率最高,流物件通常會提供緩衝區,以減少呼叫系統i/o庫函式的次數。

一共有三種緩衝型別:

全緩衝:直到緩衝區被填滿,才呼叫系統i/o函式。對於讀操作來說,直到讀入的內容的位元組數等於緩衝區大小或者檔案已經到達結尾,才進行實際的i/o操作, 將外存檔案內容讀入緩衝區;對於寫操作來說,直到緩衝區被填滿,才進行實際的i/o操作,緩衝區內容寫到外存檔案中。磁碟檔案通常是全緩衝的。

行緩衝:直到遇到換行符』\n』,才呼叫系統i/o庫函式。

對於讀操作來說,遇到換行符』\n』才進行i/o操作,將所讀內容讀入緩衝區;

對於寫操作來說, 遇到換行符』\n』才進行i/o操作,將緩衝區內容寫到外存中。

由於緩衝區的大小是有限的,所以當緩衝區被填滿時,即使沒有遇到換行符』\n』,也同樣會 進行實際的i/o操作。

當流涉及到乙個終端時,通常使用行緩衝。

無緩衝:沒有緩衝區,資料會立即讀入或者輸出到外存檔案和裝置上。標準出錯stderr是無緩衝的,這樣保證錯誤提示和輸出能夠及時反饋給使用者,供使用者排除錯誤。

通過一段**分別判斷 標準輸入 標準輸出 標準錯誤的緩衝情況:

#include

int main(void)

結果是全緩衝、行緩衝和無緩衝。

為什麼stdin是全緩衝呢?

在apue裡面提到

一般情況下認為:

標準錯誤是不帶緩衝的

若指向終端裝置的流則是行緩衝,否則是全緩衝的

因此,當我們在**中加入

int a;

scanf("%d",&a);

輸出就變成了:行緩衝、行緩衝、無緩衝。

另外在apue裡面還提到:

當且僅當標準輸入和標準輸出並不指向互動式裝置的時候,他們是全緩衝

標準錯誤絕對不是全緩衝

因此,可以嘗試對流進行一下重定向,看看輸出是什麼:

./buffer 1>out.txt 2>error.txt
標準輸出被重定向到out.txt檔案中,開啟該檔案,結果為:

全緩衝、全緩衝、無緩衝

還可以用乙個例子來說明:

#include

#include

#include

char buf = "zhangxiao\n";

int main()

printf("before fork()...\n");

if((pid = fork()) == -1)

if(pid == 0) //child

else

// parent

return

0;

}

直接執行./buffer2

輸出結果為:

zhangxiao

before fork()

如果執行:./buffer2 > test.txt

開啟重定向的檔案,裡面內容為:

zhangxiao

before fork()

before fork()

before fork被輸出了兩次。

首先,剛剛提到,面向終端的io預設是行緩衝的,因此printf("....\n")之後,在遇到\n緩衝區重新整理(即遇到\n時fflush緩衝)。

而重定向到檔案的緩衝方式是全緩衝,printf操作後,並沒有重新整理緩衝。

當fork子程序的時候,子程序會複製父程序的資料空間,當然包括父程序開啟的檔案描述符所對應的緩衝區

第一種情況,輸出後緩衝區已經被重新整理即清除,所以子程序不會複製這部分緩衝區;第二種情況全緩衝,不會被重新整理,所以子程序會複製這部分緩衝區,

在程式結束時才會對輸出緩衝區進行重新整理。所以最後會輸出兩次「before fork()…」,因為父程序和子程序都有自己的這部分緩衝區。

那麼為什麼在print之前的write不會出現兩次呢?因為write是不帶緩衝的io

如果不滿足系統這種預設設定,可呼叫下面兩個函式更改緩衝型別:

void serbuf(file*restrict fp,char *restrict buf);

int servbuf(file*restrict fp,char *restrict buf,int mode,size_t size);

例如,

setvbuf(stdout,null,_ionbf,0);//設定標準輸出不帶緩衝

//類似的mode還有:

//_iofbf 全緩衝

//_iolbf 行緩衝

//_ionbf 無緩衝

1.apue

2.3.

標準I O緩衝 全緩衝 行緩衝 無緩衝

說明 我只對網路資源進行了整合,方便學習 基於流的操作最終會呼叫read或者write函式進行i o操作。為了使程式的執行效率最高,流物件通常會提供緩衝區,以減少呼叫系統i o庫函式的次數。基於流的i o提供以下3種緩衝 全緩衝 直到緩衝區被填滿,才呼叫系統i o函式。對於讀操作來說,直到讀入的內容...

標準I O緩衝 全緩衝 行緩衝 無緩衝

某日一朋友寫了乙個hello world 出不來結果,如下 include intmain int argc,char argv 注意到,在 中printf語句列印的字串最後沒有帶換行符,而且最後呼叫了 exit函式,這導致了在終端螢幕上顯示不出來字串 hello world 首先介紹一下unix裡...

標準I O緩衝 全緩衝 行緩衝 無緩衝

說明 我只對網路資源進行了整合,方便學習 基於流的操作最終會呼叫read或者write函式進行i o操作。為了使程式的執行效率最高,流物件通常會提供緩衝區,以減少呼叫系統i o庫函式的次數。基於流的i o提供以下 3種緩衝 全緩衝 直到緩衝區被填滿,才呼叫系統i o函式。對於讀操作來說,直到讀入的內...