帶緩衝I/O 和不帶緩衝I/O的區別與聯繫

首先要明白不帶緩衝的概念:所謂不帶緩衝,並不是指內核不提供緩衝,而是隻單純的系統調用,不是函數庫的調用。系統內核對磁盤的讀寫都會提供一個塊緩衝(在有些地方也被稱爲內核高速緩存),當用write函數對其寫數據時,直接調用系統調用,將數據寫入到塊緩衝進行排隊,當塊緩衝達到一定的量時,纔會把數據寫入磁盤。因此所謂的不帶緩衝的I/O是指進程不提供緩衝功能(但內核還是提供緩衝的)。每調用一次write或read函數,直接系統調用。
帶緩衝的I/O是指進程對輸入輸出流進行了改進,提供了一個流緩衝,當用fwrite函數網磁盤寫數據時,先把數據寫入流緩衝區中,當達到一定條件,比如流緩衝區滿了,或刷新流緩衝,這時候纔會把數據一次送往內核提供的塊緩衝,再經塊緩衝寫入磁盤。(雙重緩衝)
因此,帶緩衝的I/O在往磁盤寫入相同的數據量時,會比不帶緩衝的I/O調用系統調用的次數要少。

        看正常情況下,和磁盤交互的讀寫文件是怎麼個流程!

        當應用程序嘗試讀取某塊數據的時候,如果這塊數據已經存放在頁緩存中,那麼這塊數據就可以立即返回給應用程序,而不需要經過實際的物理讀盤操作。當然,如果數據在應用程序讀取之前並未被存放在頁緩存中(也就是上面提到的內核高速緩存),那麼就需要先將數據從磁盤讀到頁緩存中去。對於寫操作來說,應用程序也會將數據先寫到頁緩存中去(這裏所說的寫到頁緩存中,如果是調用標準庫I/O進行寫,那麼首先是寫到標準庫的緩衝區內,如果標準庫的緩衝區寫滿以後,在寫到頁緩衝內;如果是系統調用,那麼直接寫到頁緩衝內),數據是否被立即寫到磁盤上去取決於應用程序所採用的寫操作機制:如果用戶採用的是同步寫機制,那麼數據會立即被寫回到磁盤上,應用程序會一直等到數據被寫完爲止;如果用戶採用的是延遲寫機制,那麼應用程序就完全不需要等到數據全部被 寫回到磁盤,數據只要被寫到頁緩存中去就可以了。在延遲寫機制的情況下,操作系統會定期地將放在頁緩存中的數據刷到磁盤上。與異步寫機制不同的是,延遲寫機制在數據完全寫到磁盤上得時候不會通知應用程序,而異步寫機制在數據完全寫到磁盤上得時候是會返回給應用程序的。所以延遲寫機制本省是存在數據丟失的風險的,而異步寫機制則不會有這方面的擔心。

        下面聊聊不帶緩衝的I/O

不帶緩存,不是直接對磁盤文件進行讀取操作,像read()和write()函數,它們都屬於系統調用,只不過在用戶層沒有緩存,所以叫做無緩存IO,但對於內核來說,還是進行了緩存,只是用戶層看不到罷了。

帶不帶緩存是相對來說的,如果你要寫入數據到文件上時(就是寫入磁盤上),內核先將數據寫入到內核中所設的緩衝儲存器,假如這個緩衝儲存器的長度是100個字節,你調用系統函: 
    ssize_t write (int fd,const void * buf,size_t count);
    寫操作時,設每次寫入長度count=10個字節,那麼你幾要調用10次這個函數才能把這個緩衝區寫滿,此時數據還是在緩衝區,並沒有寫入到磁盤,緩衝區滿時才進行實際上的IO操作,把數據寫入到磁盤上,所以上面說的“不帶緩存""不是沒有緩存而是沒有直寫進磁盤就是這個意思(既然沒有寫入磁盤,調用系統調用爲何可以在文件中看到寫入的內容呢,因爲內核控件是共享的)

    那麼,既然不帶緩存的操作實際在內核是有緩存器的,那帶緩存的IO操作又是怎麼回事呢?

    帶緩存IO也叫標準IO,符合ANSI C 的標準IO處理,不依賴系統內核,所以移植性強,我們使用標準IO操作很多時候是爲了減少對read()和write()的系統調用次數,帶緩存IO其實就是在用戶層再建立一個緩存區,這個緩存區的分配和優化長度等細節都是標準IO庫代你處理好了,不用去操心,還是用上面那個例子說明這個操作過程:

    上面說要寫數據到文件上,內核緩存(注意這個不是用戶層緩存區)區長度是100字節,我們調用不帶緩存的IO函數write()就要調用10次,這樣系統效率低,現在我們在用戶層建立另一個緩存區(用戶層緩存區或者叫流緩存),假設流緩存的長度是50字節,我們用標準C庫函數的fwrite()將數據寫入到這個流緩存區裏面,流緩存區滿50字節後在進入內核緩存區,再調用系統函數write()將數據寫入到內核緩衝內,如果內核緩衝也被填滿,或者內核進行fflush操作,那麼內核緩衝區內數據就別寫入到文件(實質是磁盤)上,看到這裏,你用該明白一點,標準IO操作fwrite()最後還是要掉用無緩存IO操作write,這裏進行了兩次調用fwrite()寫100字節也就是進行兩次系統調用write()。

    如果看到這裏還沒有一點眉目的話,那就比較麻煩了,希望下面兩條總結能夠幫上忙:
    無緩存IO操作數據流向路徑:數據——內核緩存區——磁盤
    標準IO操作數據流向路徑:數據——流緩存區——內核緩存區——磁盤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章