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

Read Ahead


Rev.5を表示中。最新版はこちら

編集中

概要

ファイルのRead処理ではファイルを後ろの方へシーケンシャルに読んでいくことが多いため、LinuxカーネルはファイルのあるブロックをReadすると、指定されたブロックから先のブロックもまとめてReadする(先読み)ようになっている。これには、以下のようなメリットがある。

  • ファイルはディスク上に連続ブロックに配置されている可能性が高いため、ディスクヘッドの動きを小さくなりI/Oが効率化できる。
  • ディスクへのI/O回数をまとめることでI/Oが効率化できる。
  • 先にデータを読み込んで置くことで、アプリケーションが頻繁にI/O待ちしなくて済むようになる。

基本動作


実装

page_cache_readahead(*mapping, *ra, *filp, offset, req_size)

先読みを行なう大元のルーチン

page_cache_readahead()の処理の概要


/* 前回の先読みからシーケンシャルなアクセスになっているかチェック */
sequential = (offset == ra->prev_page + 1);
ra->prev_page = offset;
:
:
if (sequential && ra->size == 0) {
    /* ファイルへの初回アクセス時の処理 */
    :
    goto out;
}
if (!sequential) {
    /* ランダムアクセス時の処理 */
    ra_off(ra);  /* Read AheadをDisable */
    blockable_page_cache_readahead(mapping, filp, offset,
                                   newsize, ra, 1);
    goto out;
}

/* 以下はReadAheadの基本ケースの処理 */

/* ahead windowがまだ作成されていなければ
 * 作成してI/O開始。
 */
if (ra->ahead_start == 0) {
    if (!make_ahead_window(mapping, filp, ra, 0))
        goto out;
}

/* current windowを読みきって、ahead windowに到達したら
 * 現在のahead windowをcurrent windowにして
 * make_ahead_window()で新しいahead windowを作成。
 * ahead windowのRead I/Oも開始される。
 */
if (ra->prev_page >= ra->ahead_start) {
    ra->start = ra->ahead_start;
    ra->size = ra->ahead_size;
    make_ahead_window(mapping, filp, ra, 0);
}
out:
    return ra->prev_page + 1;
make_ahead_window(*mapping, *filp, *ra, force)
次のAhead Windowを作成してI/Oを開始する。


blockable_page_cache_readahead(*mapping, *filp, offset, nr_to_read, block)
指定ファイル(mapping)のページオフセットoffsetからnr_to_read分のデータを先読みする。blockが設定されていたら、Read完了までBlockする。

read_pages(*mapping, *filp, *pages, nr_pages)

ページデータの読みこみルーチン。
ファイルのページリード用ハンドラ(mapping->a_ops->readpages)を呼び出して、pagesで指定されたページのデータを読みこんでPageCacheに入れる。



最終更新 2007/02/12 18:16:42 - kztomita
(2007/02/11 20:09:39 作成)
添付ファイル
window.png - kztomita


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