帶與不帶緩衝的I O

2021-06-20 15:00:19 字數 2930 閱讀 9600

帶快取的檔案操作

是標準c庫的實現。第一次呼叫帶快取的檔案操作函式時,標準庫會自動分配記憶體並且讀出一段固定大小的內容儲存在快取中。所以以後每次的讀寫操作並不是針對硬碟上的檔案直接進行的,而是針對記憶體中的快取的。何時從硬碟中讀取檔案或者向硬碟中寫入檔案有標準庫的機制控制。

不帶快取的檔案操作通常都是系統提供的系統呼叫,更加低階,直接從硬碟中讀取和寫入檔案,由於io瓶頸的原因,速度並不如意,而且原子操作需要程式設計師自己保證,但使用得當的話效率並不差。另外標準庫中的帶快取檔案io 是呼叫系統提供的不帶快取io實現的。

「術語不帶緩衝指的是每個read和write都呼叫嗯核心中的乙個系統呼叫。所有的磁碟i/o都要經過核心的塊緩衝(也稱核心的緩衝區快取記憶體),唯一例外的是對原始磁碟裝置的i/o。既然read或write的資料都要被核心緩衝,那麼術語「不帶緩衝的i/o「指的是在使用者的程序中對這兩個函式不會自動緩衝,每次read或write就要進行一次系統呼叫。」--------摘自

程式中用open和write開啟建立並把「hello world「寫入檔案test.txt,相應用fopen和fwrite操作檔案test2.txt。程式執行到open和fopen之後,sleep 15秒,這時用ls檢視生成了檔案沒,這時用open開啟的test.txt出現了,但是fopen的test2.txt沒有;當程式執行完write和fwrite之後,fopen的test2.txt仍然沒有出現(還是用ls檢視),再用cat看test.txt,可以看到 「helloworld」;最後再關閉test.txt和test2.txt,這時test2.txt出現了,並且其內容也是「hello world「。

該例子證明了open和write是不帶緩衝的,即程式一執行其io操作也立即執行,不會停留在系統提供的緩衝裡,不需等到close操作完才執行。與之相比的fopen和fwrite則是帶緩衝的,(一般)要等到fclose操作完後才會執行。

相關的原始碼示例如下:

#include

#include

#include

#include

#include

#include

using namespace std;

int main()

if((file=fopen("test2.txt","w"))==null)

cout<<"file has been opened."<

cout<<"write error"<

return -1;

}

if(fwrite(s,sizeof(char),strlen(s),file)

cout<<"write error in 2."<

return -1;

}

cout<<"after write"<

sleep(15);

cout<<"after sleep."<

close(fd);

return 0;}

先來看看不帶快取的i/o和標準(帶快取的)i/o都有那些

不帶快取的i/o:read,write,open......

標準(帶快取的)i/o:fgets,fread,fwrite.....

這裡使用兩個對應的函式進行比較:

ssize_t write(int filedes, const void *buff, size_t nbytes)

size_t fwrite(const void *ptr, size_t size, size_t nobj, file *fp)

上面的buff和ptr都是指應用程式自己使用的buffer,實際上當需要對檔案進行寫操作時,都會先寫到核心所設的緩衝儲存器。如果該快取未滿,則並不將其排入輸出佇列,直到快取寫滿或者核心再次需要重新使用此快取時才將其排入磁碟i/o輸入佇列,再進行實際的i/o操作,也就是此時才把資料真正寫到磁碟,這種技術叫延遲寫。

如果我們直接用非快取i/o對核心的緩衝區進行讀寫,會產生許多管理不善而造成的麻煩(如一次性寫入過多,或多次系統呼叫導致的效率低下)。標準(帶快取的)i/o為我們解決了這些問題,它處理很多細節,如緩衝區分配,以優化長度執行i/o等,更便於我們使用。

由於標準(帶快取的)i/o在系統呼叫的上一層多加了乙個緩衝區,也因此引入了流的概念,在unix/linux下表示為file*(並不限於unix/linux,ansi c都有file的概念),file實際上包含了為管理流所需要的所有資訊:實際i/o的檔案描述符,指向流快取的指標(標準i/o快取,由malloc分配,又稱為使用者態程序空間的快取,區別於核心所設的快取),快取長度,當前在快取中的位元組數,出錯標誌等。

因此可知,不帶快取的i/o對檔案描述符操作,帶快取的標準i/o是針對流的

標準i/o對每個i/o流自動進行快取管理(標準i/o函式通常呼叫malloc來分配快取)。它提供了三種型別的快取:

1) 全快取。當填滿標準i/o快取後才執行i/o操作。磁碟上的檔案通常是全快取的。

2) 行快取。當輸入輸出遇到新行符或快取滿時,才由標準i/o庫執行實際i/o操作。stdin、stdout通常是行快取的。

3) 無快取。相當於read、write了。stderr通常是無快取的,因為它必須盡快輸出。

一般而言,由系統選擇快取的長度,並自動分配。標準i/o庫在關閉流的時候自動釋放快取。另外,也可以使用函式fflush()將流所有未寫的資料送入(重新整理)到核心(核心緩衝區),fsync()將所有核心緩衝區的資料寫到檔案(磁碟)

在標準i/o庫中也有引入快取管理而帶來的缺點--效率問題。例如當使用每次一行函式fgets和fputs時,通常需要複製兩次資料:一次是在核心和標準i/o快取之間(當呼叫read和write時),第二次是在標準i/o快取(通常系統分配和管理)和使用者程式中的行快取(fgets的引數就需要乙個使用者行快取指標)之間。

帶緩衝的IO和不帶緩衝的IO

首先說說帶緩衝的i o是什麼意思,在unix環境高階程式設計裡面,是這樣解釋的 術語不帶緩衝指的是每個read和write都呼叫核心中的乙個系統呼叫。所有的磁碟i o都要經過核心的塊緩衝 也稱核心的緩衝區快取記憶體 唯一例外的是對原始磁碟裝置的i o。既然read或write的資料都要被核心緩衝,那...

帶緩衝的IO和不帶緩衝的IO

檔案描述符 檔案描述符是乙個小的非負整數,是核心用來標識特定程序正在訪問的檔案 標準輸入 輸出 出錯 shell為每個程式開啟了三個檔案描述符,stdin fileon,stdout fileon,stderr fileon,預設這三個檔案描述符都鏈向終端 不帶緩衝的io 函式open read w...

帶緩衝I O 和 不帶緩衝I O詳解

帶快取的檔案操作 是標準c 庫的實現,第一次呼叫帶快取的檔案操作函式時標準庫會自動分配記憶體並且讀出一段固定大小的內容儲存在快取中。所以以後每次的讀寫操作並不是針對硬碟上的檔案直接進行的,而是針對記憶體中的快取的。何時從硬碟中讀取檔案或者向硬碟中寫入檔案有標準庫的機制控制。不帶快取的檔案操作通常都是...