詳解Linuxカーネルの9章プロセスアドレス空間に関連する、メモリリージョンを操作する関数を読んだ。
カーネルバージョン
v4.1.10
データ構造
プロセスから見える仮想アドレス空間の情報はtask_struct->mm
で管理される。
割り当てるメモリリージョンはmm_struct->mm_rb
のRed-blackツリーでメモリ番号順にソートされた、vm_area_struct
の単位で管理される。
メモリリージョンが管理するメモリの領域は開始・終了アドレスであらわす。
unsigned long vm_start; /* Our start address within vm_mm. */
unsigned long vm_end; /* The first byte after our end address within vm_mm. */
これらのデータ構造はカーネル内のメモリの確保と解放を管理するだけで、ページテーブルへの登録は別途行う必要がある(と思う)。
メモリリージョンを直接操作する関数
基本的にはmm_rbからアドレス(範囲)を指定して検索する。また、ツリーの探索を省略するためのキャッシュをプロセスごとに持っている。
2.6.x時点のmm->mmap_cache
はtask_struct->vmacache
となっていて、各プロセスごとに4つvmaのキャッシュを格納できる配列となっている。操作はvmacache_*
関数で行っている。
find_vma
addr < vm_end
となる最小のvm_area_struct
を検索する。検索対象のvm_area_structにaddrが含まれている必要はない。
-
current->vmacache
を検索 - mm_rbを検索し、対象のvmaがあればreturn、なかった場合はNULL。
find_vma_intersection
引数のアドレス範囲start_addr, end_addr
と重なるvmaを返す。
find_vma(mm, start_addr)
の戻り値に対して、end_addr <= vma.vm_start
となるかどうか。
その他
空き範囲の検索、リージョンの追加のための関数がある。
ページテーブルへの追加
do_mmap
は読めていないが、関連する関数が2.6.xより大きく変わっている事がわかった。
make_page_present()
ではなく、populate_vma_page_range()
でページテーブルへの追加は行われていると思われる。