輸入輸出緩衝(I/O buffering)
緩衝區是一個等候區。想像一個衣帽寄放櫃台:人們以各種速度抵達,但櫃台在中間先收著外套,使寄放員與賓客不必步調一致。輸入輸出緩衝就是作業系統在一個快的一方與一個慢的一方之間,保有一塊記憶體——一個緩衝區——讓資料能依自己的步調堆積或排空,雙方都不必遷就對方確切的節奏。
具體來說,緩衝解決幾個不同的問題。第一,速度不匹配:程式產生資料的速度可能遠快於(或慢於)裝置所能接收的;一個緩衝區吸收這個差異,使生產者不被勒住到裝置的步調。第二,傳輸大小不匹配:磁碟喜歡一次寫入一整個區塊,但程式可能一次只寫幾個位元組;作業系統把那些小寫入收集在緩衝區裡,一次刷出一整個區塊。第三,它讓資料在傳輸期間能停駐:當一個網路封包以片段抵達時,緩衝區先把整個訊息組裝起來,再往上交付。所以一次單純的 write 往往不會直接送到裝置——它把你的位元組複製進一個核心緩衝區後就返回,真正的裝置寫入稍後才發生。
為什麼重要:緩衝是讓輸入輸出有效率、讓程式保持簡單的幕後功臣之一——你可以一次寫一個位元組,而不必每次都付出一整次磁碟操作。但它有誠實的代價與誠實的危險。代價是額外的複製與所用的記憶體。危險是被緩衝的資料尚未安全地落在裝置上:如果在 write 返回之後、緩衝區被刷出之前斷電,那筆資料就會遺失——這正是為什麼需要持久性的程式必須明確強制把緩衝區刷出(fsync),而不能相信一個已返回的 write 就代表已寫入磁碟。
你的程式把一行 40 位元組的日誌寫了一千次。作業系統不會做一千次磁碟操作,而是把它們收集在緩衝區裡,用幾個完整的 4 KB 區塊寫入磁碟——快得多,但如果在緩衝區被刷出之前斷電,最後幾行可能會遺失。
緩衝區吸收速度與大小的不匹配;代價是資料尚未落在裝置上。
緩衝與快取不一樣:緩衝區是傳輸中資料的暫存區,而快取則保留很可能被重複使用的資料副本。一個已返回的 write 只代表資料到了緩衝區,而不是磁碟。