ページフォルト - 個々のハンドラ
Rev.11を表示中。最新版はこちら。
ページフォルトの処理ルーチンhandle_pte_fault()から呼び出される個々のハンドラルーチンのメモ。
関連関数
do_anonymous_page()
Anonymous Page(匿名ページ)を割り当てるルーチン。
Anonymous Pageとはストレージと関連付けられていないページ。プロセスの.bssセグメントなどのページがこれに該当する。
プロセスが変数などにアクセスしてページが未割り当てだった場合は、ここでページが割り当てられる。0で初期化したページを割り当てるため、ごみが残っていることはない。
Anonymous Pageとはストレージと関連付けられていないページ。プロセスの.bssセグメントなどのページがこれに該当する。
プロセスが変数などにアクセスしてページが未割り当てだった場合は、ここでページが割り当てられる。0で初期化したページを割り当てるため、ごみが残っていることはない。
do_anonymous_page()の処理概要
if (write_access) { /* Writeアクセスだった */ /* HighMemから0 fillしたページを割り当て */ page = alloc_zeroed_user_highpage(vma, address); /* 割り当てたページへのPTEを作成 */ } else { /* Readアクセスだった */ /* Zero Page(ページ内が0 fillされているページ)への * PTEを作成 */ } /* 作成したPTEを設定 */ set_pte_at(mm, address, page_table, entry);
do_no_page()
何か初期データが存在するアドレス空間(*1)へのページフォルトを処理するハンドラ。
vmaに登録されているNo Page時のハンドラ(vma->vm_ops->nopage)を呼び出すことによって、該当データが格納されたページを取得してアドレス空間とのマッピングを行う。
(*1) ファイルをマップしている領域や共有領域。
vmaに登録されているNo Page時のハンドラ(vma->vm_ops->nopage)を呼び出すことによって、該当データが格納されたページを取得してアドレス空間とのマッピングを行う。
(*1) ファイルをマップしている領域や共有領域。
do_no_page()の処理概要
/* * ページフォルト時のハンドラを呼び出す。 * アドレス空間の種類によって異なるが、 * ファイルにマップされているアドレス空間では * filemap_nopage()を呼び出す。 * ハンドラはaddressに対応する空間のデータを * ページに格納して返す。 */ new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret); /* 共有領域以外へのWriteだった場合は、 * COW(Copy On Write)処理を行う */ if (write_access && !(vma->vm_flags & VM_SHARED)) { /* HighMemからページを割り当て */ page = alloc_page_vma(GFP_HIGHUSER, vma, address); /* HignMemのページへコピー (new_page => page) */ copy_user_highpage(page, new_page, address); new_page = page; anon = 1; } if (mapping && unlikely(sequence != mapping->truncate_count)) { } if (pte_none(*page_table)) { /* new_pageへのPTEを作成 */ entry = mk_pte(new_page, vma->vm_page_prot); /* Write属性を必要なら設定 */ if (write_access) entry = maybe_mkwrite(pte_mkdirty(entry), vma); /* PTE(page_table)を設定して、物理ページをマッピング */ set_pte_at(mm, address, page_table, entry); } else { }
do_swap_page()
do_swap_page()の処理概要
page = lookup_swap_cache(entry);
if (!page) {
/* Swap Cacheに存在しない */
swapin_readahead(entry, address, vma);
page = read_swap_cache_async(entry, vma, address);
:
}
:
pte = mk_pte(page, vma->vm_page_prot);
if (write_access && can_share_swap_page(page)) {
pte = maybe_mkwrite(pte_mkdirty(pte), vma);
write_access = 0;
}
flush_icache_page(vma, page);
set_pte_at(mm, address, page_table, pte);
page_add_anon_rmap(page, vma, address);
:
if (write_access) {
if (do_wp_page(mm, vma, address,
page_table, pmd, ptl, pte) == VM_FAULT_OOM)
ret = VM_FAULT_OOM;
goto out;
}
---------------------------
coreの採取
do_coredump()
binfmt->core_dump() - バイナリ毎のcore採取処理を呼ぶ
(ELFの場合だとelf_core_dump())
elf_core_dump()
fill_elf_header() - ELFヘッダを作成
:
ELFヘッダ書き出し
:
current->mm->mmapの全vmaに対して
ProgramHeaderを書き出す。
(vma一つが一つのセグメント)
:
current->mm->mmapの全vmaに対して...
get_user_pages()
ページを書き出す