詳解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()でページテーブルへの追加は行われていると思われる。