Linux的Page Cache
1. Page Cache
何為Page Cache
為了了解Page Cache我們可以看一下Linux的文件I/O系統
從圖中可以看出,Page Cache是由Linux內核進行管理的,而且通過mmap以及bffered I/O將文件讀取到內存空間實際上都是讀取到Page Cache上的。
如何查看系統的Page Cache?
通過讀取cat /proc/meminfo文件,查看系統實時內存情況。
... Buffers: 117572 kB Cached: 2738632 kB SwapCached: 14560 kB Active: 1444220 kB Inactive: 5806180 kB Active(anon): 509816 kB Inactive(anon): 4946608 kB Active(file): 934404 kB Inactive(file): 859572 kB ... Shmem: 1062864 kB ... Buffers + Cached + SwapCached = Active(file) + Inactive(file) + Shmem + SwapCached上述等式兩邊都是Page Cache
Page Cache = Buffers + Cached + SwapCachedPage 于Page Cache
Page 是內存管理分配的基本單位,Page Cache是由多個Page所構成的。Page在操作系統中通常都是為4KB大小,Page Cache的大小為4KB的整數倍。
另外一方面,并不是所有的Page都被認為是Page Cache
Linux系統中可供訪問的兩種內存:
- File-backed pages:文件備份頁也就是Page Cache中的Page,對應于磁盤上的若干數據塊;對于這些頁最大的問題是臟數據回盤;
- Anonymous pages: 不對應磁盤上的任何數據塊,也就是晉城運行時的內存空間(例如:方法棧、局部變量表等屬性)
為啥不直接將Page Cache稱為block cache
對比一下file-backed pages和Anonymous pages在swap機制下的性能
內存是一種珍惜資源,當內存不夠用的時候,內存管理單元MMU(memory Managment Unit)需要提供調度算法回收相關的內存空間。內存空間揮手的方式通常就是swap機制,將內存中的數據交換到持久化設設備上的過程。
File-backed pages(Page Cache)的回收代價比較低,因為:
- Page Cache通常對應于一個文件上的若干順序塊,因此我們在進行持久化落盤可以通過順序I/O的方式進行落盤。
- 如果Page Cache上沒有進行任何的寫操作(也就是沒有任何的臟頁),甚至Linux系統不會將Page Cache進行回盤,想要獲取新的內容完全可以通過再次讀取磁盤中的文件即可。
Page Cahe主要難點在于臟頁回盤(后面進行說明)
Anonymous pages內存回收代價是比較高的。這時因為Anonymous pages通常隨機地寫入持久化設備。另外一方面,無論是否有寫操作,為了確保數據不丟失,Anonymous pages在進行swap時必須持久化到磁盤上。
swap與缺頁中斷
swap機制是指物理內存不夠用的時候,內存管理單元MMU(memory Managment Unit)需要提供調度算法來回收相關的內存空間,然后將清理出來的內存空間給當前的內存申請方。
swap機制存在的原因是Linux系統提供了虛擬內存管理機制,每個一個進程都認為其獨占內存空間,因此所有的進程的內存空間之和遠遠大于物理內存,所有進程的內存空間之和超過物理內存的分部分需要交換到磁盤上。
操作系統以page為單位管理內存,當進程發現需要訪問的數據不再內存時,操作系統可能會將數據以頁的方式加載到內存中。上述的整個過程被稱之為缺頁中斷,當操作系統發生缺頁中斷時,就會通過系統調用將page再次讀取到內存中。
但主內存的空間是有限的,當主內存中不包含可以使用的空間時,操作系統會從內存中選擇合適的內存頁驅逐回磁盤,為新的內存頁讓出位置,選擇待驅逐頁的過程在操作系統中叫做頁面替換(page replacement),替換操作又會觸發swap機制。
如果物理內存足夠大,那么可能不需要 Swap 機制,但是 Swap 在這種情況下還是有一定優勢:對于有發生內存泄漏幾率的應用程序(進程),Swap 交換分區更是重要,這可以確保內存泄露不至于導致物理內存不夠用,最終導致系統崩潰。但內存泄露會引起頻繁的 swap,此時非常影響操作系統的性能。
Linux可以通過swappiness參數控制swap機制,范圍[0-100],實現控制swap的優先級:
- 高數值:較高頻率的swap,在進程不活躍時主動將其轉換出物理內存
- 低數值:較低頻率的swap,這可以確保交互式不因為內存空間頻繁的=地交換到磁盤而提高響應延遲。
為什么buffers也是Page Cache的一部分
這是因為當匿名頁(Inactive(anon) 以及 Active(anon))先被交換(swap out)到磁盤上后,然后再加載回(swap in)內存中,由于讀入到內存后原來的 Swap File 還在,所以 SwapCached 也可以認為是 File-backed page,即屬于 Page Cache。這個過程如 Figure 2 所示。
老一點的系統
~ free -mtotal used free shared buffers cached Mem: 128956 96440 32515 0 5368 39900 -/+ buffers/cache: 51172 77784 Swap: 16002 0 16001Cached 表示當前的頁緩存(Page Cache)占用量,buffers表示的是當前塊緩存(buffer Cache)占用量。
Page Cache : 用于緩存文件的頁數據
buffer Cache: 用于緩存塊設備如磁盤的塊數據
新系統
andrew@andrew-G3-3590:~$ free -m總計 已用 空閑 共享 緩沖/緩存 可用 內存: 7789 3190 627 1111 3970 3212 交換: 2047 1 2046通過上述描述,我們可以 知道Page Cache與文件系統同級別的,buffer Cache是塊物理上的概念,因此buffer Cache是與塊設備驅動程序是同級別的。
Page Cache與buffer Cache共同的目的就是為了加速數據I/O: 寫數據時首先要寫到緩存,將寫入的數據標記為dirty,想外部存儲flash(簡稱回盤)。如果讀取數據我們會先去緩存中讀取,如果在緩存中未命中,我們再去外部存儲中去讀取,并將讀取出來的數據加入到緩存中,并且操作系統總是積極的將所有的空閑內存都用作Page Cache和buffer Cache,當內存不夠用時也會使用LRU等算法淘汰緩存。
Linux2.4之前,Page Cache與buffer Cache是完全分離的,但是塊設備通常是磁盤,磁盤上的數據又大多通過文件系統來組織,這種設計方式會導致很多數據被緩存了兩次。在LInux系統2.5版本之后,系統將兩個快近似的融合在了一起,如果一個文件的頁加載到了Page Cache,那么同時Buffer Cache只需要維護塊指向頁的指針就可以了。只有那些沒有文件表示的塊,或者繞過文件系統直接操作(dd命令)的塊,才會真正的放到Buffer Cache里。后文所說的Page Cache基本上是Page Cache與buffer Cache的統稱。
Page Cache的預讀
操作系統會為基于Page Cache的讀緩存機制提供預讀機制(PAGE_READAHEAD)
舉個例子:用戶想通過系統調用獲取磁盤上文件的一段數據
- 用戶線程僅僅想讀取磁盤上對應文件的0-3KB范圍內的數據,由于磁盤的基本讀寫單位是block(4KB),于是操作系統會至少讀取4KB的內容,這4KB剛好能夠在一個Page中裝下。
- 由于操作系統出于局部最優原理,會將磁盤塊offset[4,8],[9,12]以及[1316]都加載到內存
經過上述操作,我們只是想通過read讀取4KB的內容,但是系統預讀取了16KB的內容。
2. Page Cache與文件持久化的一致性&可靠性
現在LInux的Page Cache正如其名,是對磁盤上Page的內存緩存,同時可以用于讀寫操作。任何系統引入緩存,就會引發一致性問題:內存中的數據與磁盤中的數據不一致,例如后端常見的Redis緩存和MySQL數據庫的一致性問題
吞吐量與數據一致性是一對不可調和的矛盾(硬件一致的情況下)
什么是文件
文件其實是數據和元數據的組合,文件=數據+元數據。
元數據:用來描述文件的各種屬性,元數據也必須存儲在磁盤上
因此,我們在保證數據一致性的時候其實包含了兩個方面:數據一致+元數據一致
# drwxr-xr-x 5 andrew andrew 4096 4月 24 16:43 snap # 元數據包含的內容 # 1. 文件的大小 # 2. 創建時間 # 3. 訪問的時間 # 4. 屬主和屬組等信息 # 5. 屬主權限信息文件一致性
發生寫操作的時候,我們會把對應的數據寫到Page Cache中,如果此時數據還沒有刷新到磁盤中,那么內存中的數據就領先于磁盤,此時Page就被稱為Dirty page。
當前的lInux有兩種方式實現文件一致性:
| fsync(int fd) | 將fd代表的文件的臟數據和臟元數據刷新到磁盤中 |
| fdatasync(int fd) | 將fd代表的文件的臟數據刷新到磁盤,同時對必要的元數據刷新到磁盤,必要信息是指對文件有關鍵作用的信息。文件大小、文件修改時間就不屬于必要信息了。 |
| sync() | 對系統中的所有臟數據和臟元數據刷新到磁盤中 |
3. Page Cache的優勢與劣勢
優勢
劣勢
參考:
《Linux內核詳解》
視頻教程
Linux I/O - Page Cache詳解(一)
Linux I/O - Page Cache詳解(二)
Linux I/O - Page Cache詳解(三)
Linux I/O - Page Cache詳解(四)
飛書加入團隊一起創作:
Linux的Page Cache
https://ny5odfilnr.feishu.cn/docs/doccn0dfIAin7tGfryiXo6wFTmg
關注公眾號,一起探討學習:
總結
以上是生活随笔為你收集整理的Linux的Page Cache的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 作者:王融,中国信息通信研究院互联网法律
- 下一篇: 软件测试——实验二