Linux Kernel(2.6)の実装に関するメモ書き

PageCache


1. 概要

LinuxのディスクキャッシュはPageCacheとして実装されている。PageCacheはストレージ上のファイルをキャッシュする(*1)。PageCacheはファイルの先頭から物理ページサイズ単位に区切ってページ単位にキャッシュする。このため、"Page"Cacheと呼ばれる。

ファイルのRead/WriteはPageCacheを経由する。

(*1) 同じようなディスクキャッシュとしてBufferがある。Bufferはファイルではなくディスクブロックをキャッシュする。こちらはi-nodeなどのディスク上のメタデータなどをブロックリードする時などに使用される。

2. PageCacheの管理方法

2.1 address_space構造体

PageCacheはstruct address_space (*1)を元に管理される。

図1にページキャッシュがstruct address_spaceでどのように管理されるかを示す。

  1. address_spaceはi-node単位に存在し、i-nodeに対応するファイル/ディレクトリのページキャッシュを管理する。
  2. address_spaceはRadixTreeを持ちここにキャッシュしたページを登録して管理している。
  3. RadixTreeのキーはaddress space内でのオフセット(ページ数)(*2)。よって、オフセットから高速にキャッシュを検索できる。
  4. 1.〜3.より、ページキャッシュはinode(正確にはaddress space)とファイル先頭からのオフセット(ページ数)でユニークに識別される。
(*1) ファイルをディスクキャッシュとしてメモリ空間上にマッピングした"アドレス空間"を管理するため"address_space"というネーミングになっていると思われる。
(*2) i-nodeがブロックデバイスの場合はaddress spaceはデバイス全体を指すのでデバイス先頭からのページ数になる。



図1 PageCacheの構造

以下は図1に関する補足。

  • inodeのi_mappingは、このinodeに対応するaddress_spaceを指す。
  • address_spaceのhostはinodeを指す。ブロックデバイスだった場合は、ブロックデバイスのinodeを指している。
  • page_treeはPageCacheであるRadixTreeへのポインタ。
  • RadiXTreeにはページオフセットをキーにpage構造体が登録されている。
  • pageのmappingは属しているaddress_spaceを指す(つまりinodeのaddress_space)。
  • indexはファイル先頭からのオフセットで、そのページがファイルの何処をキャッシュしているかを示している。
  • RadixTreeにページが登録されていても(図1中の黄色のページ)、データがキャッシュ済み(データが読み込ま済)というわけではない。ファイルリード時は、空のページキャッシュを作成後、ページキャッシュへファイルデータを読み込んでいるため、データの読み込みが完了しているかを判定するために、PG_uptodateフラグをチェックする必要がある。また、ページキャッシュにデータを書き込んで、まだディスクに書き込まれていない場合はPG_dirtyがセットされている。

2.2 LRUリスト

address_spaceに登録されたページはLRUリスト(Active/Inactiveリスト)にも登録される。最初はInactiveリストに登録される。

3. 関連関数

find_or_create_page()
PageCacheに新規ページを割り当てる。

割り当てたPageCacheはRadixTreeとLRUリストに登録される。LRUリストはInactiveリストの方につながれる。

find_or_create_page() -> add_to_page_cache_lru() -> lru_cache_add() ->  __pagevec_lru_add() -> add_page_to_inactive_list() - Inactiveリストへ登録


find_get_page(mapping, offset)
PageCacheの検索ルーチン
mappingのoffsetページをキャッシュしているPageCacheを検索する。

mapping->page_treeのRadixTreeからoffset(ページ数)でPageCacheを検索


add_to_page_cache()
PageCacheにページを追加する。
RadixTreeへの追加のみで、LRUリストには追加されない。

pageにはPG_lockedがセットされる。


add_to_page_cache_lru()
add_to_page_cache()を呼んで、RadixTreeにページを登録してLRUリストにも登録する。

remove_from_page_cache()

mark_page_accessed(page)
ページにアクセスがあった場合に呼び出される。

pageがInactiveリストに入っていたら、Activeリストに移動する。Activeリストに入っていたらPG_referencedを立てておく。


[フラグ]
PG_uptodate
ページにデータが読みこまれてキャッシュが最新の状態になるとSetPageUptodate()で設定する。
mpage_end_io_read()参照。

[関連ページ]
物理ページ管理


最終更新 2007/03/14 20:56:40 - kztomita
(2006/03/27 14:03:40 作成)
添付ファイル
pagecache.png - kztomita


リンク
最近更新したページ
検索