カーネル空間のメモリマップ
カーネルは0xc0000000以降の約1GBのアドレス空間を使用する(図1)。
この領域は物理ページ#0から順番に固定的にストレートマップされている。
カーネル空間のマップの設定契機
[参考]
init_mm - カーネルが使用するmm_struct
[関連ページ]
アドレス空間の管理
この領域は物理ページ#0から順番に固定的にストレートマップされている。
図1 メモリマップ
カーネル空間のPageDirectory
このストレートマップしているPageDirectoryはswapper_pg_dirに格納されている。立ち上げ時に初期化される。カーネル空間のアドレスマップの作成
arch/i386/mm/init.c
paging_init()
pagetable_init()
:
kernel_physical_mapping_init(swapper_pg_dir)
カーネルアドレス空間(0xc0000000〜)を物理メモリへストレートマップ
(max_low_pfnページ分をマップ)
<--全物理ページ分
swapper_pg_dirの先にPageDirectoryが作成される。
swapper_pg_dirをCR3に設定してストレートマップ完了
各プロセスPageDirectoryへのコピー
各プロセスのPageDirectoryにもカーネル空間(0xc0000000-)のマップが入っていて、システムコールを発行してカーネル内に入って来た時でも、プロセスのPageDirectoryをそのまま使えるようになっている。カーネル空間のマップの設定契機
fork()してプロセスを生成する時にpgd_alloc()でPageDirectoryを作成するが、ここでswapper_pg_dirの内容がコピーされる。
pgd_alloc()内でPageDirectoryの領域を確保する際、kmem_cache_alloc()でスラブアロケータのpgd_cacheからメモリを取得する。pgd_cacheにはコンストラクタpgd_ctor()が設定されており、メモリ取得の際pgd_ctor()で初期化される。
pgd_ctor() - pgd_cacheのコンストラクタ
pgd_alloc()内でPageDirectoryの領域を確保する際、kmem_cache_alloc()でスラブアロケータのpgd_cacheからメモリを取得する。pgd_cacheにはコンストラクタpgd_ctor()が設定されており、メモリ取得の際pgd_ctor()で初期化される。
pgd_ctor() - pgd_cacheのコンストラクタ
swapper_pg_dirから0xc0000000以降のエントリを確保したPageDirectoryの該当部分にコピー(PageTableはinit_mmと同じものを使用することになる)
マップが固定の部分(ストレートマップ部分)はこれで良いが、vmalloc()のようにあとからマップが変わる部分は各プロセスのマップをどのように更新する?
- vmalloc()した時点でinit_mm.pgdにはPDE,PTEが設定される。
- 各プロセスのコンテキストでVMALLOC領域にアクセスした時、ページフォルトが発生
- do_page_fault()::vmalloc_fault:でinit_mmの該当PDEをプロセスコンテキストのPDEにコピー(set_pmd()マクロ)して、ページにアクセスできるようになる。(PageTableはinit_mmと共用することになるのでPTEの更新は不要)
逆に領域解放時は各プロセスのPageDirectoryでUnmapできる? (ごみが残ったりしない?)
- vfree()してもPDEは更新しない。PTEをクリアするのみ。
- PageTableは共用しているので、どのプロセスのコンテキストからもページへのアクセスはできなくなるので問題ない。
[参考]
init_mm - カーネルが使用するmm_struct
コンパイル時にINIT_MM()マクロで初期化されている。
init_mm.pgdには上記のストレートマップしたPageDirectory(swapper_pg_dir)のアドレスが格納されている。
init_mm.pgdには上記のストレートマップしたPageDirectory(swapper_pg_dir)のアドレスが格納されている。
vmalloc()の領域で確保された領域はここで管理される?
swapper_pg_dirの中身
0xc0358be0 <swapper_pg_dir+3040>: 0x00000000 0x00000000
0x00000000 0x00000000
0xc0358bf0 <swapper_pg_dir+3056>: 0x00000000 0x00000000
0x00000000 0x00000000
0xc0358c00 <swapper_pg_dir+3072>: 0x000001e3 0x004001e3
0x008001e3 0x00c001e3
0xc0358c10 <swapper_pg_dir+3088>: 0x010001e3 0x014001e3
0x018001e3 0x01c001e3
0xc0358c20 <swapper_pg_dir+3104>: 0x020001e3 0x024001e3
0x02bfe163 0x02ffe163
[関連ページ]
アドレス空間の管理