Linux檔案緩衝區詳解

2021-06-11 01:10:59 字數 4763 閱讀 9495

華清遠見嵌入式學院講師。

a)緩衝區機制

根據應用程式對檔案的訪問方式,即是否存在緩衝區,對檔案的訪問可以分為帶緩衝區的操作和非緩衝區的檔案操作:

a) 帶緩衝區檔案操作:高階標準檔案i/o操作,將會在使用者空間中自動為正在使用的檔案開闢記憶體緩衝區。

b) 非緩衝區檔案操作:低階檔案i/o操作,讀寫檔案時,不會開闢對檔案操作的緩衝區,直接通過系統呼叫對磁碟進行操作(讀、寫等),當然用於可以在自己的程式中為每個檔案設定緩衝區。

兩種檔案操作的解釋和比較:

1、非緩衝的檔案操作訪問方式,每次對檔案進行一次讀寫操作時,都需要使用讀寫系統呼叫來處理此操作,即需要執行一次系統呼叫,執行一次系統呼叫將涉及到cpu狀態的切換,即從使用者空間切換到核心空間,實現程序上下文的切換,這將損耗一定的cpu時間,頻繁的磁碟訪問對程式的執行效率造成很大的影響。

2、ansi標準c庫函式 是建立在底層的系統呼叫之上,即c函式庫檔案訪問函式的實現中使用了低階檔案i/o系統呼叫,ansi標準c庫中的檔案處理函式為了減少使用系統呼叫的次數,提高效率,採用緩衝機制,這樣,可以在磁碟檔案進行操作時,可以一次從檔案中讀出大量的資料到緩衝區中,以後對這部分的訪問就不需要再使用系統呼叫了,即需要少量的cpu狀態切換,提高了效率。

b)緩衝型別

標準i/o提供了3種型別的緩衝區。

1、全緩衝區:這種緩衝方式要求填滿整個緩衝區後才進行i/o系統呼叫操作。對於磁碟檔案的操作通常使用全緩衝的方式訪問。第一次執行i/o操作時,ansi標準的檔案管理函式通過呼叫malloc函式獲得需要使用的緩衝區,預設大小為8192。

//come from /usr/include/stdio.h

/* default buffer size. */

#ifndef bufsiz

# define bufsiz _io_bufsiz        //bufsiz 全域性巨集定義

#endif

//come from /usr/include/libio.h

#define _io_bufsiz _g_bufsiz

//come from /usr/include/_g_config.h

#define _g_bufsiz 8192        //真實大小

2、行緩衝區:在這種情況下,當在輸入和輸出中遇到換行符時,標準i/o庫函式將會執行系統呼叫操作。當所操作的流涉及乙個終端時(例如標準輸入和標準輸出),使用行緩衝方式。因為標準i/o庫每行的緩衝區長度是固定的,所以只要填滿了緩衝區,即使還沒有遇到換行符,也會執行i/o系統呼叫操作,預設行緩衝區的大小為1024。

下面的兩個程式的對比可以得出行緩衝的大小:

3、無緩衝區:

無緩衝區是指標準i/o庫不對字元進行快取,直接呼叫系統呼叫。標準出錯流stderr通常是不帶緩衝區的,這使得出錯資訊能夠盡快地顯示出來。

注:①標準輸入和標準輸出裝置:當且僅當不涉及互動作用裝置時,標準輸入流和標準輸出流才是全緩衝的。②標準錯誤輸出裝置:標準出錯絕不會是全緩衝方式的。

對於任何乙個給定的流,可以呼叫setbuf()和setvbuf()函式更改其緩衝區型別。

此函式第乙個引數為要操作的流物件,第二個引數buf 必須指向乙個長度bufsiz 的緩衝區。如果將buf 設定為null,則關閉緩衝區。如果執行成功,將返回0,否則返回非0 值。

此函式第乙個引數為要操作的流物件;第二個引數buf 必須指向乙個長為bufsiz 的緩衝區;第三個引數為緩衝區型別,分別定義如下:

//come from /usr/include/stdio.h

/* the possibilities for the third argument to 'setvbuf'. */

#define _iofbf 0 /* fully buffered.*/        //全緩衝

#define _iolbf 1 /* line buffered. */        //行緩衝

#define _ionbf 2 /* no buffering. */        //無緩衝

第四個引數為該buf的大小。如果指定乙個不帶緩衝區的流,則忽略buf和size引數。

如果指定全緩衝區或行緩衝區,則buf 和size 可選擇地指定乙個緩衝區及其長度。如果出現指定該流是帶緩衝區的,而buf 是null,則標準i/o 庫將自動為該流分配適當長度的緩衝,適當長度指的即是由檔案屬性資料結構(struct stat)的成員st_blksize 所指定的值,如果系統不能為該流決定此值(例如若此流涉及乙個裝置或乙個管道),則分配長度bufsiz 的緩衝區。

此函式如果執行成功,將返回0,否則返回非0 值。

以下是乙個修改 buf 大小寫檔案的例項程式。其源**如下:

#include < stdio.h>

#include < stdlib.h>

int main()

setbuf(fp,null);

fwrite(msg1,7,1,fp);

printf("test setbuf(no buf)!check no_buf1.txt\n");//檢視 buf 情況

printf("press enter to continue!\n");

getchar();

fclose(fp);//關閉流,因此將回寫 buf(如果有 buf 的話)

/*開啟(或者建立)乙個檔案,然後使用 setvbuf 設定為 nobuf 情況,並檢查關閉前流的情況*/

if((fp = fopen("no_buf2.txt","w")) == null)

setvbuf(fp,null,_ionbf,0);         //設定為無 buf

fwrite(msg1,7,1,fp);

printf("test setbuf(no buf)!check no_buf1.txt\n");        //檢視 buf 情況

printf("press enter to continue!\n");

getchar();

fclose(fp);//關閉流,因此將回寫 buf ( 如果有 buf 的話)

if((fp = fopen("1_buf.txt","w")) == null)

setvbuf(fp,buf,_iolbf,sizeof(buf));        //設定為行 buf

fwrite(msg2,sizeof(msg2),1,fp);        //寫內容

printf("test setvbuf(line buf)!check 1_buf.txt,because line buf,only data before enter send to file\n");        //檢視 buf 情況

printf("press enter to continue!\n");

getchar();

fclose(fp);        //關閉流,因此將回寫 buf

//開啟(或者建立)乙個檔案,然後使用 setvbuf 設定為全 buf情況,並檢查關閉前流的情況

if((fp = fopen("f_buf.txt","w")) == null)

setvbuf(fp,buf,_iofbf,sizeof(buf));

for(i = 0;i < 2;i++)

printf("test setbuf(full buf)! check f_buf.txt\n");

printf("press enter to continue!\n");

getchar();

fclose(fp);//關閉流,因此將回寫 buf

return 0;

}其編譯過程及執行結果如下:

編譯:執行:

以下內容是在過程中檢視各檔案內容資訊:

[njs@njs]#cat no_buf1.txt

hello,w //寫入的7 個字元全部寫入到檔案中

[njs@njs]#cat no_buf2.txt

hello,w //寫入的7 個字元全部寫入到檔案中

[njs@njs]#cat l_buf.txt

hello //只有回車前的字元寫入

[njs@njs]#cat f_buf.txt //沒有任何內容寫入

執行過程完成後:

[njs@njs]#cat no_buf1.txt

hello,w //與原來內容一樣

[njs@njs]#cat no_buf2.txt

hello,w //與原來內容一樣

[njs@njs]#cat l_buf.txt

hello

world //因為呼叫了fclose()函式,重新整理了緩衝區,將world 寫入

[njs@njs]#cat f_buf.txt

hello

world //因為呼叫了fclose()函式,重新整理了緩衝區,將hello/nworld 都寫入

linux檔案緩衝區

一 緩衝區機制 根據應用程式對檔案的訪問方式,即是否存在緩衝區,對檔案的訪問可以分為帶緩衝區的操作和非緩衝區的檔案操作 緩衝區檔案操作 高階檔案系統,將在使用者空間中自動為正在使用的檔案開闢記憶體緩衝區。非緩衝區檔案系統 低階檔案系統,如果需要,只能由使用者在自己的程式中為每個檔案設定緩衝區。如果採...

檔案緩衝區

前段我把鍵盤丟了,今天我重新買了乙個鍵盤,新鍵盤拿到手後,舊鍵盤又被我找到了!我真是 現在呢,我兩個鍵盤它也沒多大用,於是我決定把新鍵盤送給我在北京的好盆友foreb。我現在有兩個送鍵盤的方案 1.我親自護送鍵盤,打車,買機票到北京,然後跑到他家,他在家的話,直接給他,不在家我再等等他,等他回來了給...

linux緩衝區解析

緩衝區是記憶體的一部分空間,用緩衝輸入輸出的資料。緩衝區又分為輸入緩衝區和輸出緩衝區。緩衝區又被稱為快取.主要的意義就是為了提高cpu的效率。輸入端。假如沒有緩衝區,我們要從磁碟中讀取資料,有幾個字元,cpu就要讀寫幾次,cpu是高速率的,而讀取是低速率的,這樣做會降低cpu的效率。相反如果將資料都...