Default Pagerは補助記憶装置へのPageOut/PageInを行う。
Default
Pagerには管理用の構造体としてvstructがある。vstructとvm_objectとの関係を図1に示す。vm_objectのpagerが指すmemory_objectのpager値がISVSの値だとmemory_objectはvstructであることを意味する(vstructの先頭4Byteはmemory_objectと共有する)。
図1 vstruct
表1 vstructの内容(一部)
フィールド
| 内容 |
|---|
| vs_mem_obj | memory_objectとの共用部分。ISVS(123456)の値が入っているはず。 |
vs_control
| memory_object_controlへのポインタ。ここ経由でvm_objectへ遡ることができる。
|
| vs_readers | 処理中のReadRequest数
|
vs_writers
| 処理中のWriteRequest数 |
vs_indirect
| クラスタマップがIndirectマップ。(vsu_imapが有効)
|
vsu_dmap
| クラスタのDirectマップ(vs_indirect == FALSEの時有効)
|
| vsu_imap | クラスタのInirectマップ(vs_indirect == TRUEの時有効) |
vsmap
VM
Object内のクラスタ(PageIn/Outはクラスタ単位で行われる)のデータがどこに補助記憶装置のどこに置かれているかを調べるためにvsmapがある。VM
Objectのサイズが小さい時は、vstructのvs_dmapにDirectマップが構築され、サイズが大きくなるとvs_imapにIndirectマップが構築される。クラスタ毎にvsmapが1エントリ存在する。図2参照。
このマップからVM
Objectが示すRegionの先頭からのオフセットからクラスタ番号を求めvsmapを取得すると対応するPageing
Segment(ページアウトされているデバイスやファイル)を取得できる。
vsmap_psindexにはPaging
Segmentへのポインタが入っており、これはPageOut時に設定される。PageInの時はこのvsmapに登録された情報にしたがってデータを読み込む。
Paging Segment
仮想記憶を行う上でページアウトするデバイス、パーティション毎にPaging Segmentが作成されて管理される。Paging
Segmentはpaging_segments[]からまとめて管理される(図3)。
各Paging
Segmentは各Segmentの空き容量を管理する。ps_pgnumが総ページ数でps_clcountが実際の空き容量となる(クラスタ数。ps_clshiftだけ右シフトするとページ数になる)。
Paging Segmentはdefault_pager_add_file(),
default_pager_add_segment()によって作成される。default_pager_add_file()はスワップファイルをPagerに登録するルーチンでmacx_swapon()から呼ばれる。default_pager_add_segment()はスワップパーティションをPagerに登録するルーチン。
図3 Paging Segment
[関連関数]
dp_memory_object_data_request()
PageIn処理を行うDefault Pagerのエントリルーチン。
dp_memory_object_data_return()
PageOut処理を行うDefault Pagerのエントリルーチン。
default_pager_memory_object_create()
vstructを構築する。
vm_object_pager_create()でVM ObjectにDefault
Pagerを割り当てる時に使われる。Default PagerはVM
Objectが作成された時には作られず、PageOut時にはじめて作成される。
pvs_cluster_read(vs, vs_offset, cnt)
クラスタの読み込み処理
UPLを作成してps_read_file()に処理を渡す。
最終的にはBSD側に実装されているPageIn処理(vnode_pagein())へ。
vs_cluster_write()
クラスタの書き込み処理
CL_FIND無しでps_clmap()を呼び出すことで該当vsmapにまだPaging
Segmentが割り当てられていなかった場合は、新たに割り当てる。どのPaging
Segmentを選ぶかはps_select_segment()で決めているみたい。