Linuxの備忘録とか・・・(目次へ)Linuxの備忘録とか・・・(目次へ)逆マッピングユーザプロセスのページを回収する時、ページだけでなく、そのページを参照しているページテーブルエントリーも回収処理(ページが割り当てられていない等のフラグセット)をしなければなりません。それが共有ページで、他のプロセスに参照されているページだと、それがどのプロセスが参照しているか検索する必要があります。そのプロセスのページテーブルエントリーも回収処理しなければならないからです。そこで、ページから参照しているページテーブルを取得する機能が必要となります。この機能を逆マッピングと言うのだそうです。(逆マッピングの機能が無ければすべてのプロセスのページテーブルをフル検索しなければなりません。)ページ割り当ては遅延割り当てとして、ページ例外処理の中のhandle_pte_fault関数で行われます。無名ページ割り当てはdo_anonymous_page関数がコールされます。0;}do_anonymous_page関数で実ページが割り当てられ、ページディスクリプター/ページテーブルの種々の設定を施します。逆マッピングに関してはpage_add_new_anon_rmap関数をコールすることで行います。page_add_new_anon_rmap関数では、page->_mapcount=0(0はそのページの参照が1つと言うことです。参照しない場合は-1。新規割り当てのため他に参照していないため0で初期化)を設定したのち、__page_set_anon_rmap関数で逆マッピングの実設定を行います。vma->anon_vmaを設定するだけです。設定するvma->anon_vmaアドレスにPAGE_MAPPING_ANON(1)加えた値を設定しています。これは物理ページが無名ページかそうでないか判断するためで、vma->anon_vmaはページアライメントされており(たぶん)、これでpage->mappingの下位ビットが1ならそのページは無名ページと判断できる分けです。これで、このページのpage->mappingから、vma->anon_vmaが取得でき、list_head構造体をメンバーに持つanon_vma(共有ページするたびに、そのanon_vmaにvm_area_structをリスト登録するようになっています。vm_mmから、ページテーブルが取得できるわけです。page->mappingに直接ページテーブルのアドレスを設定すればいいではないか。共有ページのページディスクリプターに直接逆マップ処理を施すとなると、共有する毎にページディスクリプター自身にその処理(その共有するプロセスのページテーブルのリスト)を施す必要があります。fork関数で子プロセスを作成した場合を見てみると、子プロセスはページテーブル/メモリディスクリプタは独自に確保しますか、プロセス毎の独自の設定した後、実たる中身は親と同じで、そして物理ページそのものを共有します。従ってその子プロセス作成の処理は負荷の低い処理を実現しています。物理ページ毎に逆マッピングの処理を施していたら、そのすべての無名ページに対して、ページ毎の子プロセスのページテーブルのリストを追加する処理が必要となってきまう。メモリー使用効率から言っても、同じページテーブルをページ個別にリスト追加するのは避けたいものです。forrk()->copy_process()->copy_mm()->dup_mm()->dup_mmap()とコールされます。dup_mmap関数では親プロセスのvm_area_struct構造体(メモリーリージョン)の中身をコピーしていく処理です。その処理の中でanon_vma_link関数がコールされ、子プロセスのvm_area_structを子プロセスのanon_vmaにリスト登録していきます。vm_area_structの中身は親プロセスと同じものでした。子としてリスト登録したanon_vmaは、親と同じanon_vmaだということです(vm_area_structのanon_vmaポインターメンバーが、親子とも同じと言う事)。従ってpage->mappingのanon_vmaを辿ることで、ページを参照している各プロセス毎のvm_area_struct構造体がわかり、ページテーブルが参照できるということです。}}無名ページの回収はtry_to_unmap_anon関数で行います。構造体を取得し、それを引数としてtry_to_unmap_one関数で、ページテーブルおよびページの回収を行うことができるわけです。ノースAdsense広告情報が設定されていません。