LINUX頁快取記憶體和頁回寫

2021-06-18 23:34:17 字數 3435 閱讀 4039

from:

頁快取記憶體是linux核心實現的一種主要磁碟快取,它主要用來減少對磁碟的io操作,具體地講,是通過把磁碟中的資料快取到物理記憶體中,把對磁碟的訪問變為對物理記憶體的訪問。為什麼要這麼做呢?

一,速度,訪問磁碟的速度要遠低於訪問記憶體的速度

臨時區域性原理,短時期內集中訪問同一片資料的原理。

有關這兩個概念,相信熟悉作業系統的我們不會太陌生。頁快取記憶體是由ram中的物理頁組成的,快取中的每一頁都對應著磁碟中的多個塊。每當核心開始執行乙個頁io操作時,就先到快取記憶體中找。這樣就可以大大減少磁碟操作。

乙個物理頁可能由多個不連續的物理磁碟塊組成。也正是由於頁面中對映的磁碟塊不一定連續,所以在頁快取記憶體中檢測特定資料是否已被快取就變得不那麼容易了。另外linux頁快取記憶體對被快取頁的範圍定義的非常寬。快取的目標是任何基於頁的物件,這包含各種型別的檔案和各種型別的記憶體對映。為了滿足普遍性要求,linux使用定義在linux/fs.h中的結構體address_space結構體描述頁快取記憶體中的頁面,如下: ?

12

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

structaddress_space ;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

structaddress_space_operations ;

這裡面最重要的兩個就是readpage()與writepage()了。對於readpage()方法而言,首先,乙個address_space物件和乙個偏移量會被傳給該方法,這兩個引數用來在頁快取記憶體中搜素需要的資料: ?1?

1

2

3

4

5

6

7

interror;

if(!cached_page)

/* error allocating memory */

if(error)

/* error adding page to page cache */

? 1

2

3

4

status = a_ops->prepare_write(file, page, offset, offset+bytes);

page_fault = filemap_copy_from_user(page, offset, buf, bytes);

status = a_ops->commit_write(file, page, offset, offset+bytes);

首先,在頁快取記憶體中搜尋需要的頁,如果需要的頁不在快取記憶體中,那麼核心在快取記憶體中新分配一空閒項;下一步,prepare_write()方法被呼叫,建立乙個寫請求;接著資料被從使用者空間拷貝到核心緩衝;最後通過commit_write()函式將資料寫入磁碟。

因為在任何頁io操作前核心都要檢查頁是否已經在頁快取記憶體中了,所以這種檢查必須迅速,高效。否則得不償失了。前邊已經說過,也快取記憶體通過兩個引數address_space物件和乙個偏移量進行搜尋。每個address_space物件都有唯一的基樹(radix tree),它保證在page_tree結構體中。基樹是乙個二叉樹,只要指定了檔案偏移量,就可以在基樹中迅速檢索到希望的資料,頁快取記憶體的搜尋函式find_get_

page()要呼叫函式radix_tree_lookup(),該函式會在指定基樹中搜尋指定頁面。基樹核心**的通用形式可以在檔案lib/radix-tree.c中找到,另外想要使用基樹,需要包含標頭檔案linux/radix_tree.h.

在記憶體中累積起來的髒頁必須被寫回到磁碟,在一下兩種情況下,髒頁會被寫會到磁碟:

1.在空閒記憶體低於乙個特定的閾值時,核心必須將髒頁寫回磁碟,以便釋放記憶體。

2.當髒頁在記憶體中駐留超過一定的閾值時,核心必須將超時的髒頁寫會磁碟,以確保髒頁不會無限期地駐留在記憶體中。

3. 當使用者程序呼叫sync()和fsync()函系統呼叫時,核心會按要求執行回寫動作。

現在你只需知道,2.6核心中,使用pdflush後台回寫例程來完成這個工作,(注:flusher執行緒,具體可以檢視linux kernel development, fuli ma)那麼具體是怎麼實現的呢:

首先,pdflush執行緒在系統中的空閒記憶體低於乙個特定的閾值時,將髒頁重新整理回磁碟。該後台回寫例程的目的在於在可用物理記憶體過低時,釋放髒頁以重新獲得記憶體。上面提到的特定的記憶體閾值可以通過dirty_background_ratio系統呼叫設定。一旦空閒記憶體比這個指小時,核心便會呼叫函式wakeup_bdflush() 喚醒乙個pdflush執行緒,隨後pdflush執行緒進一步呼叫函式background_writeout()開始將髒頁寫會到磁碟,函式background_writeout()需要乙個長整型引數,該引數指定試圖寫回的頁面數目。函式background_writeout會連續地寫會資料,直到滿足一下兩個條件:

1.已經有指定的最小數目的頁被寫回到磁碟。

2.空閒記憶體頁已經回公升,超過了閾值dirty_background_ration.

pdflush執行緒(實現在mm/pdflush.c中,回寫機制的實現**在檔案mm/page-writeback.c和fs/fs-writeback.c中)週期地被喚醒並且把超過特定期限的髒頁寫回磁碟。系統管理員可以在/proc/sys/vm中設定回寫相關的引數,也可以通過sysctl系統呼叫來設定它們。下表給出了可以設定的量:

16 頁快取記憶體和頁回寫

頁快取記憶體有什麼作用?主要實現linux的磁碟快取,用來減少磁碟的io操作,具體講就是把磁碟中資料快取到物理記憶體,把對磁碟的訪問轉換為對物理記憶體的訪問。磁碟快取記憶體為什麼這麼重要?什麼是臨時區域性原理?在短期內訪問同一片資料區的原理稱為臨時區域性原理 頁快取記憶體有什麼特點?頁快取記憶體的大...

頁快取記憶體與頁回寫

訪問物理記憶體的速度遠快於訪問磁碟的速度 所以把經常使用的資料快取到物理記憶體 頁快取記憶體 訪問磁碟可直接變為訪問物理記憶體的方式 頁快取記憶體是由記憶體中的物理頁面組成的 內容對應磁碟上的物理塊 讀快取當核心開始乙個讀操作時 它首先會檢查需要的資料是否再頁快取記憶體中 如果在就放棄訪問磁碟 直接...

第16章 頁快取記憶體和頁回寫

磁碟訪問ms級別,記憶體訪問ns級別,使用資料務必將資料拷貝到記憶體中,這裡是將一些磁碟資料對映到記憶體中提高命中率。對應於磁碟的物理塊 對映關係 可以占用空閒記憶體擴張,也可以收縮 換出 read操作 讀取一段資料,首先在快取中查詢,沒有的話才呼叫i o去安排,讀取就直接讀取到快取中,一段時間沒有...