檔案讀寫之I O緩衝與阻塞

2021-06-20 12:13:26 字數 2042 閱讀 1664

緩衝i/o和非緩衝i/o

檔案讀寫主要牽涉到了如下五個操作:開啟、關閉、讀、寫、定位。在linux系統中,提供了兩套api,一套是c標準api:fopen

、fclose

、fread

、fwrite

、fseek

,另一套則是posix定義的系統api:open

、close

、read

、write

、seek

。其中posix定義的api是系統api,而c標準api是基於系統api的封裝,並且提供了額外的緩衝的功能。因此也可以把它們叫做緩衝i/o函式和非緩衝i/o函式。

除了前面介紹的這幾個緩衝io函式外,c標準庫裡面還提供了一系列封裝的io函式:如puts、putchar、printf等。

為什麼要有增加緩衝區這個功能呢?主要是因為io操作時,作業系統要從使用者態轉換為核心態的,而這個轉換過程相對來說比較慢,因此可以通過緩衝的形式減少轉換到核心態的次數。那麼,緩衝io函式又是如何工作的呢?

當用fopen開啟檔案時,除了分配檔案控制代碼外,還額外申請了乙個緩衝區。

讀檔案時,會首先讀到緩衝區中,然後返回使用者需要的部分,多餘的部分仍然放在緩衝區,下次再讀的時候可以直接從緩衝區中返回。

寫檔案時,會先寫到緩衝區中,等緩衝區滿後再統一寫到檔案中。

那麼,我們該如何選擇哪一組i/o函式呢?

非緩衝i/o函式每次讀寫都要進核心,調乙個系統呼叫比調乙個使用者空間的函式要慢很多,所以在使用者空間開闢i/o緩衝區還是必要的。

ps:嚴格來講,就算是posix的i/o函式,仍然是有核心i/o緩衝的,所以write也不一定是直接寫到檔案的,也可能寫到核心i/o緩衝區中,至於究竟寫到了檔案中還是核心緩衝區中對於程序來說是沒有太大差別的,我們不用太關注這一點。

阻塞i/o和非阻塞i/o

檔案讀寫通常有阻塞和非阻塞兩種方式,其中阻塞方式是我們比較常見的一種方式,此時函式會阻塞至操作完成。例如,對於如下乙個等待使用者輸入字串,並在螢幕上輸出的例子:

#include

#include

intmain(void)

執行該函式時,read函式會一直阻塞到在螢幕上輸入資料並回車(此時stdin有資料可用)為止。

阻塞io有乙個很大的問題是:無法實現併發。當同時進行多個io操作的時候,前面的檔案資料不可用的時候(往往是socket之類的ipc操作),後面的io操作無法執行。

非阻塞io則可以很好的解決這個問題,要使用非阻塞io操作,需要在open的時候制定o_nonblock標誌。這樣,如果裝置暫時沒有資料可讀就返回-1,呼叫者應該試著再讀一次(again)。這種行為方式稱為輪詢(poll),呼叫者只是查詢一下,而不是阻塞在這裡死等,這樣可以同時監視多個裝置:

#include

#include

#include

intmain(void)

write(stdout_fileno, buf, n);

close(fd);

return0;

}ps:為了示例函式簡單,我這裡沒有考慮異常情況(如open失敗)的處理,而這些是在實際專案中是必不可少的。

非阻塞i/o有乙個缺點,如果所有裝置都一直沒有資料到達,呼叫者則需要反覆查詢,這樣會一直佔著cpu不放。因此,在使用非阻塞i/o時,通常不會在乙個while迴圈中一直不停地查詢(這稱為tight loop),而是每延遲等待一會兒來查詢一下,以免做太多無用功,在延遲等待的時候可以排程其它程序執行。

但是,這樣又引入了乙個新的問題,可能導致資料讀取的不夠及時,就拿我前面的例子來說,我在每次迴圈的時候sleep了一秒。如果剛開始sleep的時候資料可用,但此時卻無法立即響應,需要到sleep結束後鍾才能輸出結果。

要解圓滿解決這個問題,則需要用到select函式,它可以阻塞地同時監視多個裝置,還可以設定阻塞等待的超時時間,由於select多見於socket程式設計場景,這裡不大好舉例,後續如果會介紹socket程式設計的時候再詳細介紹它,要了解它的工作原理可以看一下這篇文章select,多路同步i/o模型。

檔案與IO 三 之緩衝流

首先要明確乙個概念 對檔案或其它目標頻繁的讀寫操作,效率低,效能差。使用緩衝流的好處 能夠更高效的讀寫資訊,原理是將資料先緩衝起來,然後一起寫入或者讀取出來。緩衝流的幾個方法 bufferedinputstream 為另乙個輸入流新增一些功能,在建立bufferedinputstream時,會建立乙...

Linux 檔案IO 緩衝與非緩衝

本地普通檔案io一般關注的是快取,一般都是同步阻塞的。普通檔案的file descriptor是block也是posix標準。這點不同於網路io,網路io要考慮傳輸兩邊程序處理等,設計之初就提供了帶狀態檢測的非同步操作方式,本地檔案io則必然要求高可靠性的。不帶緩衝指的是每個read和write都呼...

IO之阻塞與非阻塞比較

對於網路程式設計的更多詳細說明建議參考下面的書籍 unix網路程式設計 tcp ip 詳解 unix環境高階程式設計 非阻塞io和阻塞io 在網路程式設計中對於乙個網路控制代碼會遇到阻塞io和非阻塞io的概念,這裡對於這兩種socket先做一下說明 基本概念 socket的阻塞模式意味著必須要做完i...