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

2021-08-29 02:14:48 字數 2682 閱讀 7739

先來看看不帶快取的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的引數就需要乙個使用者行快取指標)之間。

不管上面講的到底懂沒懂,記住一點:

使用標準i / o例程的乙個優點是無需考慮快取及最佳i / o長度的選擇,並且它並不比直接呼叫read、write慢多少。

帶快取的檔案操作是標準c 庫的實現,第一次呼叫帶快取的檔案操作函式時標準庫會自動分配記憶體並且讀出一段固定大小的內容儲存在快取中。所以以後每次的讀寫操作並不是針對硬碟上的檔案直接進行的,而是針對記憶體中的快取的。何時從硬碟中讀取檔案或者向硬碟中寫入檔案有標準庫的機制控制。不帶快取的檔案操作通常都是系統提供的系統呼叫,更加低階,直接從硬碟中讀取和寫入檔案,由於io瓶頸的原因,速度並不如意,而且原子操作需要程式設計師自己保證,但使用得當的話效率並不差。另外標準庫中的帶快取檔案io 是呼叫系統提供的不帶快取io實現的。

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

標準io庫操作是圍繞著流來進行的,當我們通過fopen標準io庫函式開啟乙個檔案,我們就使乙個檔案和乙個io流相關聯。在這裡我們把io流和檔案指標file*等同起來,因為所有針對io流的操作都是通過file*指標來實現的。

我們知道引入標準io庫的目的是為了提高io的效率,避免頻繁的進行read/write系統呼叫,而系統呼叫會消耗較多的資源。因此標準io庫引入了io快取,通過累積一定量的io資料後,然後集中寫入到實際的檔案中來減少系統呼叫,從而提高io效率。標準io庫會自動管理內部的快取,不需要程式設計師介入。然而,也正是因為我們看不到標準io庫的快取,有時候會給我們帶來一定的迷惑性。這裡介紹下標準io庫的快取策略。

一。標準i/o的快取--標準輸出為例:(這裡都是指預設情況下)

1)當stdout連線到終端裝置時,那麼它就是行快取的,也就是標準io庫沒看到乙個新行符 \n時就重新整理一次快取(即執行一次實際的輸出操作)。這一特性可以通過如下測試**來驗證

int main()

2)當stdout被重定向到乙個具體檔案時,那麼標準輸出是全快取的,也就是說只有當輸出快取被塞滿或者呼叫fflush或fclose時才會執行實際的寫入操作,這裡就不給出具體例子,可以通過freopen將stdout重定向到乙個具體檔案來進行測試。

二。標準出錯stderr:為了盡快的看到出錯資訊,標準出錯是不帶任何快取的

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