檔案流緩衝區
每個程序都各自維護一個檔案流表,和檔案描述符表類似,並且這些檔案流都有自己對應的緩衝區
緩衝區的設計就是為了減少磁碟io,加快io的速度
緩衝區模式
透過setvbuf或者setbuf兩個函式設定緩衝區的模式
無緩衝區
就是禁用緩衝區的意思,這種模式下,就相當於直接呼叫write函式,不過在呼叫write之前可能還要處理一些格式化輸出等問題,這是和直接呼叫write的一個小區別
行緩衝區
當標準輸出(或者輸入)定向到終端時,預設採用行緩衝模式,就是接收到換行符就重新整理緩衝區
塊緩衝區
當緩衝區的資料達到一個塊的大小時,重新整理緩衝區,重定向時,預設使用塊緩衝區
全緩衝區
當資料填滿緩衝區時,重新整理緩衝區
總結對比
特性 | 無緩衝區(No Buffering) | 行緩衝區(Line Buffering) | 塊緩衝區(Block Buffering) | 全緩衝區(Full Buffering) |
---|---|---|---|---|
定義 | 資料不經過緩衝,直接寫入目標裝置 | 每當輸入一行資料時,才進行輸出 | 資料以塊為單位進行緩衝,達到塊大小後輸出 | 資料在緩衝區中,直到填滿後一次性輸出 |
重新整理時機 | 每次寫入操作都立即重新整理 | 每當遇到換行符時重新整理 | 當緩衝區滿或達到特定塊大小時重新整理 | 緩衝區滿或顯式呼叫重新整理時才輸出 |
記憶體使用 | 無額外記憶體開銷 | 較少的記憶體開銷 | 預定的塊大小記憶體開銷 | 較大的記憶體開銷,通常是輸出的總大小 |
效能 | 頻繁I/O操作,效能較低 | 適合逐行處理,效能適中 | 減少I/O操作,提高效能 | 適合長時間不需要輸出的場景,效能較高 |
適用場景 | 實時處理要求高的場景 | 互動式程式或逐行輸出 | 大資料處理或檔案寫入 | 批處理或需要大量輸出的場景 |
實時反饋 | 反饋及時 | 逐行反饋 | 反饋延遲,直到塊大小達到 | 反饋延遲,直到緩衝區滿 |
與fork和exit之間的互動
fork函式用於建立子程序,這樣的話子程序會複製一份父程序的stdio流緩衝區
exit函式在呼叫_exit函式前,會重新整理所有stdio流緩衝區
這兩個配合起來,有時候就會發現有的輸出列印了兩份,這是因為緩衝區沒有及時重新整理的原因,有以下幾種辦法
- 可以設定緩衝區模式
- 使用fflush立即重新整理
- 父程序使用exit函式在程式結束後重新整理,子程序使用_exit函式退出,該函式不重新整理緩衝區
所以在有多程序的情況下使用stdio流,要注意緩衝區的模式,以及何時重新整理緩衝區,避免出現意外情況