c標準I/O的緩存

這篇博客簡單介紹了標準輸入/輸出相關的緩存機制。
標準輸入/輸出庫是由IOS C定義的,與直接使用系統(tǒng)調用進行讀、寫相比,標準輸入/輸
出幫助我們處理了很多細節(jié),比如:緩存分配、一次讀、寫的合適大小等。但標準輸入
輸出庫的緩存機制也會引發(fā)很多其他問題。

令人困惑的輸出....

printf是標準I/O庫函數函數之一,看下面一段程序

#include <stdio.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    printf("hello standard I/O");
    sleep(5);
    printf(" after 5 seconds\n");
    sleep(5)
    printf("after another 5 seconds\n");
}

上述程序很簡單,咋一看這個程序的運行過程應當是:

1. 輸出字符串hello standard I/O
2. 睡眠5秒鐘
3. 輸出字符串after 5 seconds
4. 睡眠5秒鐘
5. 輸出字符after anthor 5 seconds
6. 退出程序

然而,如果實際運行的過程是:

1. 睡眠5秒鐘
2. 輸出字符串hello standard I/O
3. 輸出字符串after 5 seconds
4. 睡眠5秒鐘
5. 輸出字符串after anthor 5 seconds
6. 退出程序

為什么會這樣呢?因為printf是有緩存區(qū)的,只有在特定情況(比如遇到換行符)下才會
刷新緩存區(qū),真正向屏幕輸出字符串,這就是為什么hello standard I/O并不會馬上輸出
,而是等5秒后和after 5 seconds一起輸出。
深入到printf緩存機制內部,我們重新解析上面程序運行過程,這時這段程序其實并不
像看起來那么簡單:

1. printf函數收到輸出字符串hello standard I/O的請求, 字符串先進入緩存區(qū),沒達到
刷新緩存區(qū)的條件,并不真正地輸出字符串
2. 睡眠5秒鐘
3. printf函數再次收到輸出字符串after 5 seconds\n的請求,字符串進入緩存區(qū),緩存區(qū)
的字符串包含換行符,調用操作系統(tǒng)調用,輸出緩存區(qū)內換行符前的所有字符串:
hello standard I/O after 5 seconds
4. 睡眠5秒鐘
5. printf函數收到輸出字符串after anthor 5 seconds\n的請求,字符串進入緩存區(qū),緩存
區(qū)的字符串包含換行符,調用操作系統(tǒng)調用,輸出緩存區(qū)內換行符前的所有字符串:
after anthor 5 seconds

緩存

絕大多數標準I/O函數都包含緩存,這意味著某些情況下,一個針對磁盤的寫請求只是更新了
緩沖區(qū),要等到滿足某些條件時,才會真正刷新緩沖區(qū)的變更到磁盤。緩存是為了減少系統(tǒng)
調用的次數,提高I/O效率,因為類似刷新緩存區(qū)到磁盤的操作需要系統(tǒng)調用,
而系統(tǒng)調用開銷比較大。

標準I/O函數中有3種類型的緩存

  1. 全緩存(fully buffered)
    只有緩存區(qū)滿了的情況下,才會刷新緩存區(qū)
  2. 行緩存(line buffered)
    行緩存一般用于終端輸入和輸出
    行緩存刷新緩存的情況有
    2.1. 遇到換行符
    2.2. 緩存區(qū)滿了
    2.3. 輸入流是無緩存或者行緩存類型,輸入前,會刷新所有的行緩存類型的輸出流
  3. 無緩存(unbuffered)

更高效I/O

標準I/O中的緩存導致了數據不必要的重復拷貝,即數據先從內核拷貝到標準I/O的緩存區(qū),
然后數據從標準緩存區(qū)拷貝到用戶指定的地址中。有一些庫試圖通過減少這種拷貝來提高
I/O讀寫效率

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容