linux的cache原理,Linux Page Cache的工作原理

1 、前言

自從誕生以來,Linux 就被不斷完善和普及,目前它已經成為主流通用操作系統之一,使用得非常廣泛,它與Windows、UNIX 一起占據了操作系統領域幾乎所有的市場份額。特別是在高性能計算領域,Linux 已經成為一個占主導地位的操作系統,在2005年6月全球TOP500 計算機中,有 301 台部署的是 Linux 操作系統。因此,研究和使用 Linux 已經成為開發者的不可回避的問題了。

下面我們介紹一下 Linux 內核中文件 Cache 管理的機制。本文以 2.6 系列內核為基准,主要講述工作原理、數據結構和算法,不涉及具體代碼。

2 操作系統和文件 Cache 管理

操作系統是計算機上最重要的系統軟件,它負責管理各種物理資源,並向應用程序提供各種抽象接口以便其使用這些物理資源。從應用程序的角度看,操 作系統提供了一個統一的虛擬機,在該虛擬機中沒有各種機器的具體細節,只有進程、文件、地址空間以及進程間通信等邏輯概念。這種抽象虛擬機使得應用程序的 開發變得相對容易:開發者只需與虛擬機中的各種邏輯對象交互,而不需要了解各種機器的具體細節。此外,這些抽象的邏輯對象使得操作系統能夠很容易隔離並保 護各個應用程序。

對於存儲設備上的數據,操作系統向應用程序提供的邏輯概念就是"文件"。應用程序要存儲或訪問數據時,只需讀或者寫"文件"的一維地址空間即可,而這個地址空間與存儲設備上存儲塊之間的對應關系則由操作系統維護。

在 Linux 操作系統中,當應用程序需要讀取文件中的數據時,操作系統先分配一些內存,將數據從存儲設備讀入到這些內存中,然后再將數據分發給應用程序;當需要往文件 中寫數據時,操作系統先分配內存接收用戶數據,然后再將數據從內存寫到磁盤上。文件 Cache 管理指的就是對這些由操作系統分配,並用來存儲文件數據的內存的管理。 Cache 管理的優劣通過兩個指標衡量:一是 Cache 命中率,Cache 命中時數據可以直接從內存中獲取,不再需要訪問低速外設,因而可以顯著提高性能;二是有效 Cache 的比率,有效 Cache 是指真正會被訪問到的 Cache 項,如果有效 Cache 的比率偏低,則相當部分磁盤帶寬會被浪費到讀取無用 Cache 上,而且無用 Cache 會間接導致系統內存緊張,最后可能會嚴重影響性能。

下面分別介紹文件 Cache 管理在 Linux 操作系統中的地位和作用、Linux 中文件 Cache相關的數據結構、Linux 中文件 Cache 的預讀和替換、Linux 中文件 Cache 相關 API 及其實現。

2、 文件 Cache 的地位和作用

文件 Cache 是文件數據在內存中的副本,因此文件 Cache 管理與內存管理系統和文件系統都相關:一方面文件 Cache 作為物理內存的一部分,需要參與物理內存的分配回收過程,另一方面文件 Cache 中的數據來源於存儲設備上的文件,需要通過文件系統與存儲設備進行讀寫交互。從操作系統的角度考慮,文件 Cache 可以看做是內存管理系統與文件系統之間的聯系紐帶。因此,文件 Cache 管理是操作系統的一個重要組成部分,它的性能直接影響着文件系統和內存管理系統的性能。

3658cd5885cf5c06c64c6d46d52fd79a.png

圖1描述了 Linux 操作系統中文件 Cache 管理與內存管理以及文件系統的關系示意圖。從圖中可以看到,在 Linux 中,具體文件系統,如 ext2/ext3、jfs、ntfs 等,負責在文件 Cache和存儲設備之間交換數據,位於具體文件系統之上的虛擬文件系統VFS負責在應用程序和文件 Cache 之間通過 read/write 等接口交換數 據,而內存管理系統負責文件 Cache 的分配和回收,同時虛擬內存管理系統(VMM)則允許應用程序和文件 Cache 之間通過 memory map的方式交換數據。可見,在 Linux 系統中,文件 Cache 是內存管理系統、文件系統以及應用程序之間的一個聯系樞紐。

6b149205ab505324bbdc897dcf470499.png

3 、文件 Cache 相關數據結構

在 Linux 的實現中,文件 Cache 分為兩個層面,一是 Page Cache,另一個 Buffer Cache,每一個 Page Cache 包含若干 Buffer Cache。內存管理系統和 VFS 只與 Page Cache 交互,內存管理系統負責維護每項 Page Cache 的分配和回收,同時在使用 memory map 方式訪問時負責建立映射;VFS 負責 Page Cache 與用戶空間的數據交換。而具體文件系統則一般只與 Buffer Cache 交互,它們負責在外圍存儲設備和 Buffer Cache 之間交換數據。Page Cache、Buffer Cache、文件以及磁盤之間的關系如圖 2 所示,Page 結構和 buffer_head 數據結構的關系如圖 3 所示。在上述兩個圖中,假定了 Page 的大小是 4K,磁盤塊的大小是 1K。本文所講述的,主要是指對 Page Cache 的管理。

dfb6a16c0958817721def82455fc4da5.png

3ffef0a0ed2aacc54dcedd0c6e3a3d95.png

在 Linux 內核中,文件的每個數據塊最多只能對應一個 Page Cache 項,它通過兩個數據結構來管理這些 Cache 項,一個是 radix tree,另一個是雙向鏈表。Radix tree 是一種搜索樹,Linux 內核利用這個數據結構來通過文件內偏移快速定位 Cache 項,圖 4 是 radix tree的一個示意圖,該 radix tree 的分叉為4(22),樹高為4,用來快速定位8位文件內偏移。Linux(2.6.7) 內核中的分叉為 64(26),樹高為 6(64位系統)或者 11(32位系統),用來快速定位 32 位或者 64 位偏移,radix tree 中的每一個葉子節點指向文件內相應偏移所對應的Cache項。

e15a24e12a7d57d23da1135578e3fa48.gif

查看Page Cache的核心數據結構struct address_space就可以看到上述結構(略去了無關結構):

structaddress_space{

structinode*host;/* owner: inode, block_device */

structradix_tree_root      page_tree;/* radix tree of all pages */

unsignedlongnrpages;/*number of total pages */

structaddress_space*assoc_mapping;/* ditto */

......

}__attribute__((aligned(sizeof(long))));

下面是一個Radix Tree實例:

1881eaf9bea7efb8b879e34397f5ef22.png

另一個數據結構是雙向鏈表,Linux內核為每一片物理內存區域(zone)維護active_list和inactive_list兩個雙向 鏈表,這兩個list主要用來實現物理內存的回收。這兩個鏈表上除了文件Cache之外,還包括其它匿名(Anonymous)內存,如進程堆棧等。

de365aee821b311301b86256984cb11a.png

4 、文件Cache的預讀和替換

Linux內核中文件預讀算法的具體過程是這樣的:對於每個文件的第一個讀請求,系統讀入所請求的頁面並讀入緊隨其后的少數幾個頁面(不少於一 個頁面,通常是三個頁面),這時的預讀稱為同步預讀。對於第二次讀請求,如果所讀頁面不在Cache中,即不在前次預讀的group中,則表明文件訪問不 是順序訪問,系統繼續采用同步預讀;如果所讀頁面在Cache中,則表明前次預讀命中,操作系統把預讀group擴大一倍,並讓底層文件系統讀入 group中剩下尚不在Cache中的文件數據塊,這時的預讀稱為異步預讀。無論第二次讀請求是否命中,系統都要更新當前預讀group的大小。此外,系 統中定義了一個window,它包括前一次預讀的group和本次預讀的group。任何接下來的讀請求都會處於兩種情況之一:第一種情況是所請求的頁面 處於預讀window中,這時繼續進行異步預讀並更新相應的window和group;第二種情況是所請求的頁面處於預讀window之外,這時系統就要 進行同步預讀並重置相應的window和group。圖5是Linux內核預讀機制的一個示意圖,其中a是某次讀操作之前的情況,b是讀操作所請求頁面不 在window中的情況,而c是讀操作所請求頁面在window中的情況。

fea5d910be794530d1dc8cbe5a51aa27.gif

Linux內核中文件Cache替換的具體過程是這樣的:剛剛分配的Cache項鏈入到inactive_list頭部,並將其狀態設置為 active,當內存不夠需要回收Cache時,系統首先從尾部開始反向掃描active_list並將狀態不是referenced的項鏈入到 inactive_list的頭部,然后系統反向掃描inactive_list,如果所掃描的項的處於合適的狀態就回收該項,直到回收了足夠數目的 Cache項。Cache替換算法如圖6的算法描述偽碼所示。

圖6 Linux的Cache替換算法描述

9c49bbeafd05eb8f4c9ebe2d811877dd.gifMark_Accessed(b) {if b.state==(UNACTIVE &&UNREFERENCE)

b.state=REFERENCEelse if b.state == (UNACTIVE &&REFERENCE) {

b.state= (ACTIVE &&UNREFERENCE)

Add X to tail of active_list

}else if b.state == (ACTIVE &&UNREFERENCE)

b.state= (ACTIVE &&REFERENCE)

}

Reclaim() {if active_list not empty and scan_num< } Mark_Accessed(X) inactive_list of tail to X="head"Add into b put {else free slot if cache in not isAccess(b)

{ NULLreturn scan_num++ active_list Move UNREFERENCE | X.state 0 REFERENCE)="="

& (X.state MAX_SCAN2 scan_num="0" and emptry>9c49bbeafd05eb8f4c9ebe2d811877dd.gif

5 、文件Cache相關API及其實現

Linux內核中與文件Cache操作相關的API有很多,按其使用方式可以分成兩類:一類是以拷貝方式操作的相關接口, 如read/write/sendfile等,其中sendfile在2.6系列的內核中已經不再支持;另一類是以地址映射方式操作的相關接口,如 mmap等。

第一種類型的API在不同文件的Cache之間或者Cache與應用程序所提供的用戶空間buffer之間拷貝數據,其實現原理如圖7所示。

d7d9a86239886285229397e158711302.png

第二種類型的API將Cache項映射到用戶空間,使得應用程序可以像使用內存指針一樣訪問文件,Memory map訪問Cache的方式在內核中是采用請求頁面機制實現的,其工作過程如圖8所示。

71a37e51ac3f1972142747bcab1b0cbb.png

首先,應用程序調用mmap(圖中1),陷入到內核中后調用do_mmap_pgoff(圖中2)。該函數從應用程序的地址空間中分配一段區域 作為映射的內存地址,並使用一個VMA(vm_area_struct)結構代表該區域,之后就返回到應用程序(圖中3)。當應用程序訪問mmap所返回 的地址指針時(圖中4),由於虛實映射尚未建立,會觸發缺頁中斷(圖中5)。之后系統會調用缺頁中斷處理函數(圖中6),在缺頁中斷處理函數中,內核通過 相應區域的VMA結構判斷出該區域屬於文件映射,於是調用具體文件系統的接口讀入相應的Page Cache項(圖中7、8、9),並填寫相應的虛實映射表。經過這些步驟之后,應用程序就可以正常訪問相應的內存區域了。

6 、小結

文件Cache管理是Linux操作系統的一個重要組成部分,同時也是研究領域一個很熱門的研究方向。目前,Linux內核在這個方面的工作集中在開發更有效的Cache替換算法上,如LIRS(其變種ClockPro)、ARC等。相關信息可見linux-mm.org/AdvancedPageReplacement">http://linux-mm.org/AdvancedPageReplacement。

參考資料

Understanding Linux Kernel Edition2

Linux內核源代碼情景分析

http://www.top500.org

R.W.Carr and J.L.Hennessy. WSCLOCK - a simple and effective algorithm for virtual mem-ory management. In Proc. ACM SOSP-08, Dec 1981.

S. Jiang, F. Chen, and X. Zhang. CLOCK-Pro: An effective improvement of the CLOCK repla-cement. In Proc. USENIX ATC, Apr. 2005.

S. Jiang and X. Zhang. LIRS: an efficient low in-terreference set replacement policy to improve buffer cache performance. In Proc. ACM SIG-METRICS, June 2002.

N. Megiddo and D. S. Modha. ARC: A Self-tun-ing, Low Overhead Replacement Cache. In Proc. 2nd USENIX FAST, Mar 2003.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值