Linux 內存中的緩沖區(Buffer)與緩存(Cache)
Buffer 和 Cache 的定義:
- Buffer:是原始磁盤塊的臨時存儲,即將緩存數據寫入磁盤。它通常不會很大(大約 20MB)。這樣,內核就可以將分散的寫入集中起來,從而對磁盤寫入進行統一優化。例如,多個小的寫入可以合并為一個大的寫入等。
- Cache:是用于從磁盤讀取文件的頁面緩存,用于緩存從文件中讀取的數據。這樣,下次訪問這些文件數據時,可以直接從內存中快速取回,而無需再次訪問緩慢的磁盤。
但是讓我問你,由于 Buffer 只是將寫入磁盤的數據的緩存。反過來,它還會緩存從磁盤讀取的數據嗎?或者 Cache 是從文件中讀取數據的緩存,那么它是否也為寫入文件緩存數據呢?
如果你能回答以上兩個問題,你可以跳過這篇文章,我想你已經對 Buffer 和 Cache 有了很好的理解。但如果你不能,請留下來看看我的進一步解釋。
free 命令
要檢查系統內存使用情況,您想到的第一個命令可能是 free ,例如:
$ free -h
total used free shared buff/cache available
Mem: 1.9G 1.0G 394M 2.6M 491M 728M
Swap: 0B 0B 0B
很明顯,該輸出包括了物理內存 Mem 和 Swap 的具體使用情況(如總內存、已用內存、緩存、可用內存等)。緩存是 Buffer 和 Cache 兩部分的總和。
讓我們看一下 free 的手冊頁中的 Buffer 和 Cache 定義:
buffers
Memory used by kernel buffers (Buffers in /proc/meminfo)
cache Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)
buff/cache
Sum of buffers and cache
我們可以看到 free 命令的源數據實際上存儲在 proc/meminfo 文件中。正如我前面提到的,/proc 是 Linux 內核提供的一個特殊的文件系統,它就像一個用戶與內核交互的接口。
/proc 文件系統也是許多性能工具的最終數據源。在 man proc 中,Buffers 和 Cached 的定義如下:
Buffers %lu
Relatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so).
Cached %lu
In-memory cache for files read from the disk (the page cache). Doesn't include SwapCached.
...
SReclaimable %lu (since Linux 2.6.19)
Part of Slab, that might be reclaimed, such as caches.
SUnreclaim %lu (since Linux 2.6.19)
Part of Slab, that cannot be reclaimed on memory pressure.
至此,您可能認為您已經找到了我的問題的答案,“Buffer”只是用于將數據寫入磁盤的緩存,“Cache”只是用于從文件中讀取數據的緩存。但事實上,“Buffer”也可以用于讀取,“Cache”也可以用于寫入。
實驗
我們將在這里做兩個實驗,寫緩存和讀緩存。
寫入 Cache
讓我們登錄到我們的 Linux 主機并準備好兩個終端。在終端 1,讓我們先清理緩存:
這里 /proc/sys/vm/drop_caches 是一個通過 proc 文件系統修改內核行為的例子。寫入 3 意味著清理各種緩存,例如文件頁、目錄條目和 Inode。
仍然在終端 1,讓我們開啟 vmstat 2 命令:
- buff 和 cache 就是我們前面看到的 Buffer 和 Cache,單位是 KB。
- bi 和 bo 分別表示塊設備讀取和寫入的大小,以塊/s 為單位。由于 Linux 中的塊大小為 1KB,因此這個單位相當于 KB/s。
接下來,轉移到終端 2 并運行以下命令:
現在切換回終端 1,并觀察 buff 和 cache 的變化:
通過觀察 vmstat 的輸出,我們發現運行 dd 命令時,Cache 一直在增長,而 Buffer 基本沒有變化。
讀取 Buffer
現在,讓我們做第二個實驗。再次清除終端 1中的緩存:
同樣在終端 1 中,再次啟動 vmstat 2 命令:
您可以看到此時 buff 為 0。現在在終端 2 中,運行以下命令:
然后,回到終端 1 觀察:
觀察 vmstat 的輸出,你會發現在讀盤的時候(也就是 bi > 0 的時候),Buffer 和 Cache 都在增長,但是顯然 Buffer 的增長要快很多。這意味著當從磁盤讀取時,數據被緩存在 Buffer 中。
現在我們幾乎可以得出結論:
讀取文件時數據會緩存在 Cache 中,讀取磁盤時數據會緩存在 Buffer 中。
結論
在這里您應該會發現,雖然本文對 Buffer 和 Cache 進行了描述,但仍然無法涵蓋所有細節。我們如今學到了以下兩點:
- Buffer:既可以用作“要寫入磁盤的數據緩存”,也可以用作“讀取磁盤讀的數據緩存”。
- Cache:既可以用作“從讀取文件的頁面緩存”,也可以用作“寫入文件的頁面緩存”。