読者です 読者をやめる 読者になる 読者になる

タダノキロク

日々の考えたことの記録 主に無駄なこと

詳細Linuxカーネル 15章 ページキャッシュ 5/28

詳細Linuxカーネル 15章 ページキャッシュ 5/28

ページキャッシュの章を読む。
キャッシュは一般的にはディスクデータへのアクセスのキャッシュして RAM上に保存してシステム高速化するのが目的。

https://kernelreading.doorkeeper.jp/events/42463

15.1章 ページキャッシュとは

ページキャッシュはカーネルが使うディスクキャッシュで、 ディスクへの読み書きの際にページキャッシュを参照する。

read要求があった場合のざっくりの動作。

  1. 要求のあったデータ(ページ?)がキャッシュ上に在るか検索
  2. キャッシュ上にあればそのデータを返答
  3. キャッシュ上になければディスクから読み取りキャッシュにデータ格納。
  4. 格納したデータを返答

write要求があった場合のざっくりの動作

  1. 対応するデータ(ページ?)がキャッシュに在るか検索
  2. キャッシュ上になけれ新しいキャッシュ領域を確保
  3. キャッシュ上に書き込みデータを格納
  4. データ書き込みは適当なタイミングで実施

当たり前だがそれぞれの目的は・・・
readキャッシュの目的:同じディスク領域への複数のreadを1回のディスクアクセスにまとめる。
writeキャッシュの目的:同じディスク領域への複数のwriteを1回のディスクアクセスにまとめる。

これらの目的を満たすためには、 単なる2回のディスクアクセスより上記の手順による2回のデータアクセスが早く無いと損するはず。
そのために、以下の要件を満たしてページキャシュが実装されているらしい。
* データを含むページの迅速な検索。 (プロセスからデータアクセス時に指定してる形式はなんだっけ?忘れてる・・・)
* ページ内の内容を読み書きする手段の管理。(管理をつけた意味は?)

15.1.1 アドレス空間構造体

ページキャッシュのメインはアドレス空間(adress_space)構造体
この構造体はiノードオブジェト内に存在(inode->i_mapping)する
そのほかの構造体の関係はここがわかりやすい。

http://wiki.bit-hive.com/linuxkernelmemo/pg/PageCache

つまるところ、adress->page_treeから当該データのページディスクリプタのポインタを検索してページディスクリプタのフラグでページの状態を確認する。
adress->page_treeは基数ツリーのルートを表す。
基数ツリーの各ノードは、別のノードもしくはページのポインタを64(=26)個(配列slots)とノード内に存在するポインタ数を持つ。(その他にフラグなどある)
この基数ツリーのノードはルートからの位置indexで一意に指定している。
インデックスはファイルの先頭からのオフセットと同じ意味。
例えば、基数ツリーの深さが2つしか無いならばindex=131=64*2 + 3は ルートノードのSlot[2] -> 次のノードのSlot[3]でページディスクリプタのポインタに辿れる。

     struct radix_tree_node {
       unsigned int  path; /* Offset in parent & height from the bottom */
       unsigned int  count;
       union {
         struct {
           /* Used when ascending tree */
           struct radix_tree_node *parent;
           /* For tree user */
           void *private_data;
         };
         /* Used when freeing node */
         struct rcu_head rcu_head;
       };
      /* For tree user */
      struct list_head private_list;
      void __rcu  *slots[RADIX_TREE_MAP_SIZE];
      unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
    };

基数ツリーの最大インデックスは232-1まで。 4kB単位のページだと最大ファイルサイズは4G個 * 4kB =16TB
メモリが16TB以上とかの世界になったらどうなんだろうって思ったが、
ファイルサイズを最大16TBのことで、使えるキャッシュサイズが16TBでは無いのか。

この前提にページキャッシュの検索について見る。

この時点でざっくり性能を考えてみる。
まずは、アドレス空間構造体からページキャッシュにあるかどうかを判定するまで性能。
ファイルサイズが1GB〜64GBの範囲(階層3)と仮定する。
アドレス空間構造体からページノードにたどり着くまでに、 メモリアクセスが少なくとも4回必要(3つのノード+ページヘのポインタ参照)。
メモリが0.1μs、HDDドライブが100μs、SSDが・・・

ここからは少し考えてみる。

15.1.3 ページキャッシュの操作関数

15.1.3.1 ページの検索

ページ検索はfind_get_page()関数で * アドレス空間構造体のポインタとオフセット値を引数にする

次回は検索を見る。