link もっと前
   2008年 5月 13日 -
      2008年 5月 13日  
link もっと後

link 未来から過去へ表示(*)
link 過去から未来へ表示

日々

link permalink

struct page って何

以前から Linux のページディスクリプタ(要は struct page)って何なの?という疑問が晴れないまま居ました。特に実際のページフレームとの対応をどうやって取っているのかが全くわからん。どこかに対応が書いてあるにしては、それらしい場所がない…。

分からんながらも、機会を見つけては調べたり考えたりしていたら、なんとなーく分かった気がする。

分かった気がすることを書き散らしますが、間違っててもご勘弁下さい。自信ないです。

メモリゾーン

前提知識として簡単に説明します。Linux ではメモリ領域をゾーンという固まりで管理しています。ゾーンはページフレーム(普通は 4KB のメモリ領域)をいくつかまとめた固まりです。ページフレームがずらーっと並んでいるようなイメージ。

厳密にはもっと書くべきことがあるのでしょうが、今回はこのくらいの理解で進めるはず。たぶん。

ページディスクリプタとページフレーム

では本題に入ります。
まず私の疑問点は「ページディスクリプタ(以下、struct page)のポインタをもらったとき、どうやって対応するページフレームを得るのか?」です。

ここで struct page のメンバに直接書いてあれば話は早いのですが、struct page にページフレーム番号を示す情報などはありません。残念。

実は struct page は中身も大事ですが、ポインタ値が非常に重要な意味を持ちます。というのも実メモリのページフレームとの対応を取るために、ポインタの計算を行うからです。計算についてはまた説明します。

ページフレームを求めるためには、
ページディスクリプタ -> ゾーン -> ページフレーム
の順に求めます。まどろこしいですが、直接求められないのです。

ページディスクリプタ -> ゾーン

ページディスクリプタが対応するページフレーム、こいつが属するゾーンを求めます。自分でも何言ってるのかわかんないけど、まあいいや。

まず struct page に page_flags_t flags というメンバを見ます。こいつはその名の通りページの属性や状態を示すフラグを格納する変数なのですが、上位 3ビット(または 8ビット)だけは意味が違っていて(※1)、このページが所属するゾーンを表す数値が入っています。

なので flags >> NODEZONE_SHIFT によってページが何番目のゾーンに所属しているのかがわかります。例えば 1 だとしたら、ゾーンの配列 zone_table[1](グローバル変数)を見ればゾーンの情報が見られます(※2)。

(※1)不思議な設計に見えますが、むやみにメンバを増やすと struct page だけで相当量のメモリを圧迫(struct page はページフレームの数だけ存在する)してしまいます。

(※2)最近の Linux ではゾーンの一覧(zone_table)はグローバル配列ではありません。struct pglist_data という構造体(ゾーンが必要なら node_data というグローバル配列(アーキテクチャ依存)、ゾーンが不要なら contig_page_data という変数)経由でゾーンを見るようになっています。ゾーンが要らないというアーキテクチャを考慮したのでしょう。

ページディスクリプタ&ゾーン -> ページフレーム

長くなってきましたが、本題のページフレームの求め方に行きます。先ほど苦労して求めたゾーンには zone_mem_map というメンバが居て、ゾーンに属する struct page の一覧を持っています(※3)。


ゾーンの zone_mem_map のイメージ

上の絵で注目して欲しいのは zone_mem_map と、ページディスクリプタのポインタ(p とします)がわかれば、zone_mem_map の何番目に p が存在しているかわかるということです。上の絵では 5番目に位置しています。

薄い水色の四角内で具体的な数値(数値は適当ですが)を当てはめて p のアドレスから zone_mem_map のアドレスを引くことで、p が zone_mem_map の何番目にいるか求められる様子を示しています。


ページフレームを求める

これで struct page がゾーンの先頭から何番目のページなのかがわかりました。あとはページフレームを求めるだけです。ゾーンの構造体のメンバ zone_start_pfn がゾーンの開始ページフレーム番号を表しているので、そこへ先ほどの数字(5)を足します。

これにて struct page と対応するページフレームが求められました。

もし物理アドレスに興味があるのならば、ページフレームの番号にページフレームのサイズ(普通は 4KB のはず)を掛けてあげればよいです。
高位メモリや非連続なメモリモデルを持つアーキテクチャだと、単純に掛けるだけではダメかもしれません。

(※3)最近の Linux にはありません。恐らく zone_pgdat->node_mem_map が等価だと思われます。たぶん…。

[編集者: すずき]
[更新: 2008年 5月 14日 03:46]
link 編集する

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
   2008年 5月 13日 -
      2008年 5月 13日  
link もっと後

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 7/12 15:28

カレンダー

<2008>
<<<05>>>
----123
45678910
11121314151617
18192021222324
25262728293031

最近のコメント 5件

  • link 18年07月04日
    すずき 「NEON にも対応してみましたが、やはり...」
    (更新:07/11 21:26)
  • link 18年05月30日
    すずき 「情報ありがとうございます。PT2 2枚差...」
    (更新:06/02 17:27)
  • link 18年05月30日
    通りすがりですみませ... 「私のPC(Win10)ではB−CAS1枚...」
    (更新:06/02 16:42)
  • link 18年05月20日
    すずき 「数えたことはありませんが Windows...」
    (更新:05/22 22:26)
  • link 18年05月20日
    hdk 「Linux も、先日の Meltdown...」
    (更新:05/21 22:55)

最近の記事 3件

link もっとみる
  • link 18年07月08日
    すずき 「[Android と MPEG2-TS その 4] もはや自分以外...」
    (更新:07/12 15:28)
  • link 18年07月05日
    すずき 「[Android と MPEG2-TS その 1] Android...」
    (更新:07/08 23:26)
  • link 18年07月07日
    すずき 「[Android と MPEG2-TS その 3] デスクランブル...」
    (更新:07/08 23:21)

こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報