このページを編集する際は、編集に関する方針に従ってください。

概要

  • mm/memory.cにて定義
  • ファイルがマッピングされて無い領域(anonymous領域)の場合、この関数を利用して適当な空き物理ページを割り当てる

引数

  • mm--メモリディスクリプタ
  • vma--メモリリージョン
  • page_table--ページテーブル
  • pmd--ページディレクトリ
  • write_access--書き込みアクセスの場合は1を、読み込みアクセスの場合は0を返す
  • addr--仮想アドレス

実装

/*

* We are called with the MM semaphore and page_table_lock
* spinlock held to protect against concurrent faults in
* multithreaded programs. 
*/

static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,

		pte_t *page_table, pmd_t *pmd, int write_access,
		unsigned long addr)

{

	pte_t entry;
  • ページテーブルへ設定するエントリ
	struct page * page = ZERO_PAGE(addr);
  • ゼロページを返す。ゼロページはページフレーム割り当てを遅延させるために用いられる
    • ゼロページはグローバルな共有ページである
    • ゼロページには書き込み不可の印が付けてあるため、プロセスが書き込もうとすると、コピーオンライト機構が働く
      • この場合に限り、プロセスは書き込むことができるページを獲得することができる
    • 詳細はZERO_PAGE()/linux2.6を参照
	/* Read-only mapping of ZERO_PAGE. */
	entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
  • ゼロページを返す。ゼロページはページフレーム割り当てを遅延させるために用いられる
    • ゼロページはグローバルな共有ページである
    • ゼロページには書き込み不可の印が付けてあるため、プロセスが書き込もうとすると、コピーオンライト機構が働く
      • この場合に限り、プロセスは書き込むことができるページを獲得することができる
    • 詳細はZERO_PAGE()/linux2.6を参照
  • 引数で与えられたページからページフレーム番号を算出し対応するページテーブルエントリ(PTE)を作り返す
  • 引数で渡されたページテーブルエントリを書き込み禁止に設定する
	/* ..except if it's a write access */
	if (write_access) {
  • 書き込みアクセスの場合:
		/* Allocate our own private page. */
		pte_unmap(page_table);
  • CONFIG_HIGHPTEが無効である場合、処理を行わない
		spin_unlock(&mm->page_table_lock);
  • スピンロックmm->page_table_lockの開放を行う。プリエンプション機能を有効にし、可能であれば自ら積極的にプリエンプション(実行権の移譲を行うこと)する
		if (unlikely(anon_vma_prepare(vma)))
			goto no_mem;
  • anonymousメモリ(無名メモリ)の準備を行う
    • メモリリージョンvmaにマッピングされたanonymousメモリが無い場合は確保し、anonymousメモリのリストに追加する
    • 問題が発生しなかった場合は0を返し、問題が発生した場合はエラーコードを返す
    • anonymousメモリ(無名メモリ)とはファイルと直接関連づけられていないページ(ページ群)を指す
      • プロセスのヒープ領域、スタック、Copy-On-Writeページに対して使用される
      • Copy-On-Writeページ:ゼロページを割り当てておいて、実際に使用する際に例外を発生させ、ページの割り当てを遅延する
    • 詳細はanon_vma_prepare()/linux2.6を参照
		page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
		if (!page)
			goto no_mem;
		clear_user_highpage(page, addr);
		spin_lock(&mm->page_table_lock);
  • スピンロックmm->page_table_lockの取得を試みる
    • ロックの取得に失敗した場合は待ち状態に入る
    • 詳細はspin_lock()/linux2.6を参照
		page_table = pte_offset_map(pmd, addr);
		if (!pte_none(*page_table)) {
  • ページテーブルエントリpage_tableの有効/無効であるか調べる
    • 無効である場合は1を、有効である場合は0を返す
    • 詳細はpte_none()/linux2.6を参照
			pte_unmap(page_table);
  • CONFIG_HIGHPTEが無効である場合、処理を行わない
			page_cache_release(page);
			spin_unlock(&mm->page_table_lock);
  • スピンロックmm->page_table_lockの開放を行う。プリエンプション機能を有効にし、可能であれば自ら積極的にプリエンプション(実行権の移譲を行うこと)する
			goto out;
		}
		mm->rss++;
  • mmに割り当てられたページフレーム数を常に管理するためにrssをインクリメントする
    • この情報はシステムの最適化に用いられる
		entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
							 vma->vm_page_prot)),
				      vma);
  • pageからページフレーム番号を算出し対応するページテーブルエントリ(PTE)を作り返す
  • 引数で渡されたページテーブルエントリに更新(dirty)フラグを立てる
  • vmaが書き込み可能であれば、引数で渡されたページテーブルエントリを書き込み可能に設定する
		lru_cache_add_active(page);
  • pageをLRUキャッシュ(lru_add_active_pvecs)へ加える
		mark_page_accessed(page);
  • pageのアクティビティを設定する
    • 以下に示すような状態遷移を行う
      • inactive,unreferenced→inactive,referenced
      • inactive,referenced→active,unreferenced
      • active,unreferenced→active,referenced
    • 詳細はmark_page_accessed()/linux2.6を参照
		page_add_anon_rmap(page, vma, addr);
	}
	set_pte(page_table, entry);
  • 設定元entryのページテーブルエントリの情報を設定先page_tableのページテーブルエントリへコピーする
	pte_unmap(page_table);
  • CONFIG_HIGHPTEが無効である場合、処理を行わない
	/* No need to invalidate - it was non-present before */
	update_mmu_cache(vma, addr, entry);
	spin_unlock(&mm->page_table_lock);
  • スピンロックmm->page_table_lockの開放を行う。プリエンプション機能を有効にし、可能であれば自ら積極的にプリエンプション(実行権の移譲を行うこと)する

out:

	return VM_FAULT_MINOR;
  • VM_FAULT_MINORは1と定義
    • 副ページフォルト(minor fault)であることを意味する
      • 副ページフォルトとはカレントプロセスがブロックされることなくページフォルトが処理できたことを意味する
      • 副ページフォルトとは異なり、カレントプロセスがブロックされるページフォルトを主ページフォルト(major fault)と呼ぶ

no_mem:

	return VM_FAULT_OOM;
  • VM_FAULT_OOMは(-1)と定義
    • メモリ不足であったことを意味する

}

呼出元


履歴

  • 作者:ひら
  • 日付:2005/9/10
  • 対象:2.6.10
    更新日更新者更新内容

コメント



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-11-24 (火) 07:12:14 (2919d)