天天看點

Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構4 檔案Cache的預讀和替換

作業系統是計算機上最為重要的軟體,他負責管理計算機的各種硬體資源,并将這些實體資源抽象成各種接口供上層應用使用。是以從程式的角度看,作業系統就好比是一個虛拟機,這個虛拟機不提供各種硬體資源的具體細節,而僅僅提供程序、檔案、位址空間以及程序間通信等等邏輯概念。

對于儲存設備上的資料,作業系統向應用程式提供的邏輯概念就是“檔案”。應用程式要存儲或通路資料時,隻需要向這個檔案讀或者寫入内容即可,而檔案與實體儲存設備的互動則由作業系統提供。

檔案cache是檔案在資料記憶體中的副本,是以檔案cache管理與記憶體管理系統和檔案系統相關:一方面檔案cache作為實體記憶體的一部分,需要參與記憶體的配置設定與回收。另一方面,cache中的資料來源于儲存設備上的檔案,需要通過檔案系統與儲存設備進行讀寫互動。

如圖1所示,具體的檔案系統,比如ext2/ext2,jfs,ntfs等等負責在檔案cache和儲存設備之間交換資料,位于檔案系統之上的虛拟檔案系統vfs負責在應用程式和檔案cache之間通過read和write等接口交換資料。記憶體管理系統負責記憶體的配置設定與回收,同時虛拟記憶體管理系統(vmm)則允許應用程式和檔案cache之間通過memory map的方式交換資料。

Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構4 檔案Cache的預讀和替換

在linux的實作中,檔案cache分為兩個層面,page cache和buffer cache。每一個page cache包含若幹個buffer cache。vfs負責page cache和使用者空間的資料交換;記憶體管理系統負責page cache的配置設定與回收,同時在使用memory map通路時負責建立映射。而具體的檔案系統則與buffer cache進行互動,将外圍儲存設備上的資料和buffer cache之間進行交換。

在linux核心中,檔案的每個資料塊最多隻能對應一個page cache項,其通過兩個資料結構管理,一個radix tree另一個就是雙向連結清單。radix tree是一個搜尋樹,linux利用這個資料結構來通過檔案内偏移快速丁文cache項。下圖是radix

tree的⼀一個⽰示意圖,該radix tree

的分叉為4(22),樹⾼高為4,⽤用來快速定位8位⽂檔案内偏移。linux(2.6.7)核心中的分叉為

64(26),樹⾼高為6(64位系統)或者11(32位系統),⽤用來快速定位32

位或者64

位偏移,radix tree中的每⼀一個葉⼦子節點指向⽂檔案内相應偏移所對應的cache項。

另⼀一個資料結構是雙向連結清單,linux核心為每⼀一⽚片實體記憶體區域(zone)維護active_list和inactive_list兩個雙向連結清單,這兩個list主要⽤用來實作實體記憶體的回收。這兩個連結清單上除了⽂檔案cache之外,還包括其它匿名(anonymous)記憶體,如程序堆棧等。 

Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構4 檔案Cache的預讀和替換
Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構4 檔案Cache的預讀和替換
Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構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中的情況。

linux核心中檔案cache替換的具體過程是這樣的:剛剛配置設定的cache項鍊入到inactive_list頭部,并将其狀态設定為active,當記憶體不夠需要回收cache時,系統首先從尾部開始反向掃描active_list并将狀态不是referenced的項鍊入到inactive_list的頭部,然後系統反向掃描inactive_list,如果所掃描的項的處于合适的狀态就回收該項,直到回收了足夠數目的cache項。

linux核心中與檔案cache操作相關的api有很多,按其使用方式可以分成兩類:一類是以拷貝方式操作的相關接口, 如read/write/sendfile等,其中sendfile在2.6系列的核心中已經不再支援;另一類是以位址映射方式操作的相關接口,如mmap等。

第一種類型的api在不同檔案的cache之間或者cache與應用程式所提供的使用者空間buffer之間拷貝資料,其實作原理如圖7所示。

Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構4 檔案Cache的預讀和替換

第二種類型的api将cache項映射到使用者空間,使得應用程式可以像使用記憶體指針一樣通路檔案,memory map通路cache的方式在核心中是采用請求頁面機制實作的,其工作過程如圖8所示。

Linux核心檔案cache管理機制介紹1 作業系統和檔案Cache管理2 檔案Cache的地位和作用3 檔案Cache的相關資料結構4 檔案Cache的預讀和替換

首先,應用程式調用mmap(圖中1),陷入到核心中後調用do_mmap_pgoff(圖中2)。該函數從應用程式的位址空間中配置設定一段區域作為映射的記憶體位址,并使用一個vma(vm_area_struct)結構代表該區域,之後就傳回到應用程式(圖中3)。當應用程式通路mmap所傳回的位址指針時(圖中4),由于虛實映射尚未建立,會觸發缺頁中斷(圖中5)。之後系統會調用缺頁中斷處理函數(圖中6),在缺頁中斷處理函數中,核心通過相應區域的vma結構判斷出該區域屬于檔案映射,于是調用具體檔案系統的接口讀入相應的page

cache項(圖中7、8、9),并填寫相應的虛實映射表。經過這些步驟之後,應用程式就可以正常通路相應的記憶體區域了。

繼續閱讀