コグノスケ


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

link もっと前
2017年7月12日 >>> 2017年7月3日
link もっと後

2017年7月3日

仮想アドレスから物理アドレスへfor Linux

目次: Linux

ちょっと用事があって、ユーザプロセスの仮想アドレスから、物理アドレスへの変換を行うプログラムを作りました。名前はv2p(virt2phys)です。何の捻りもありません。ソースコードは GitHubに置いています。

やっていることは/proc/pid/pagemapを読んで、わかりやすい形式で表示しているだけです。言葉で説明するより動いている姿の方がわかりやすいと思います。

実験に使った環境はDebian GNU/Linux Testing amd64版です。別にDebianじゃなくても最近のLinuxなら動くと思います。

このツールの実行には、プロセスIDと仮想アドレスが必要です。まず解析に使うプロセスを作って、プロセスIDを調べます。

catを実行&中断
$ cat
[Press Ctrl+Z]
[1]+  Stopped                 cat

$ ps
  PID TTY          TIME CMD
 2148 pts/4    00:00:00 bash
14010 pts/4    00:00:00 cat  ★★catのPIDを覚えておく★★
14015 pts/4    00:00:00 ps

プロセスIDがわかったら、物理アドレスに変換したい仮想アドレスを決めます。ここでは例としてヒープ領域の先頭アドレスを変換しましょう。

catのヒープ領域の仮想アドレス
$ cat /proc/14010/maps
55ff09a4f000-55ff09a57000 r-xp 00000000 08:11 5505114                    /bin/cat
55ff09c56000-55ff09c57000 r--p 00007000 08:11 5505114                    /bin/cat
55ff09c57000-55ff09c58000 rw-p 00008000 08:11 5505114                    /bin/cat
55ff0b2cb000-55ff0b2ec000 rw-p 00000000 00:00 0                          [heap]    ★★これを使う★★
7fdbeb6a3000-7fdbeb838000 r-xp 00000000 08:11 4980859                    /lib/x86_64-linux-gnu/libc-2.24.so
7fdbeb838000-7fdbeba38000 ---p 00195000 08:11 4980859                    /lib/x86_64-linux-gnu/libc-2.24.so
...(snip)...
7ffdde79c000-7ffdde7be000 rw-p 00000000 00:00 0                          [stack]
7ffdde7fb000-7ffdde7fd000 r--p 00000000 00:00 0                          [vvar]
7ffdde7fd000-7ffdde7ff000 r-xp 00000000 00:00 0                          [vdso]

プロセスIDと仮想アドレスがわかったので、物理アドレスに変換します。

仮想アドレスから物理アドレスへ
$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x4000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present)
 virt:0x55ff0b2cd000, phys:(not present)
 virt:0x55ff0b2ce000, phys:(not present)

変換できました。特権のない状態で実行すると全て0x00000000になってしまいますので、お気をつけください。

表示の意味は特に何の捻りもなく、物理アドレスをそのまま示しています。ちなみに (not present) と表示される場合は、まだカーネルからページが割り当てられておらず、仮想アドレスに対応する物理アドレスが存在しないことを意味しています。

デマンドページング

これだけだとGitHubに書いたReadmeそのものだし、へぇー…って感じがするだけで面白くないので、catにgdbでアタッチしてヒープ領域を触ったらどうなるか見てみます。

gdbでアタッチして3番目と5番目のページをreadする
$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x6000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present)
 virt:0x55ff0b2cd000, phys:(not present) ★これを読む★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:(not present) ★これを読む★
 virt:0x55ff0b2d0000, phys:(not present)


$ gdb -p 14010
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...
0x00007fdbeb77e690 in __read_nocancel ()
    at ../sysdeps/unix/syscall-template.S:84
84      ../sysdeps/unix/syscall-template.S: そのようなファイルやディレクトリはありません.

(gdb) x/4x 0x55ff0b2cd000
0x55ff0b2cd000: 0x00000000      0x00000000      0x00000000      0x00000000

(gdb) x/4x 0x55ff0b2cf000
0x55ff0b2cf000: 0x00000000      0x00000000      0x00000000      0x00000000


$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x4000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present)
 virt:0x55ff0b2cd000, phys:0x1cb695000★ゼロページが割り当たる★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:0x1cb695000★ゼロページが割り当たる★
 virt:0x55ff0b2d0000, phys:(not present)

試しに3番目と5番目の領域からデータを読み出してみました、どちらも0データが見えます。読み出したあとは0x1cb695000(数字は環境によって違います)という同じアドレスが割り当たりました。このアドレスは全て0で埋まっている特殊なページを指していて、読み出したときにとにかく0データを返せば良い領域に使われるらしいです。

じゃあ今度は書いてみたらどうなるでしょう?

gdbでアタッチして2番目と3番目のページをreadする
$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x6000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:(not present) ★これに書く★
 virt:0x55ff0b2cd000, phys:0x1cb695000   ★これに書く★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:0x1cb695000
 virt:0x55ff0b2d0000, phys:(not present)


(gdb) set *((long *)(0x55ff0b2cc000))=0x89abcdef

(gdb) x/4x 0x55ff0b2cc000
0x55ff0b2cc000: 0x89abcdef      0x00000000      0x00000000      0x00000000

(gdb) set *((long *)(0x55ff0b2cd000))=0x12345678

(gdb) x/4x 0x55ff0b2cd000
0x55ff0b2cd000: 0x12345678      0x00000000      0x00000000      0x00000000


$ sudo ./src/v2p 14010 0x55ff0b2cb000 0x4000
pid: 14010:
 virt:0x55ff0b2cb000, phys:0x73a42b000
 virt:0x55ff0b2cc000, phys:0x73c76a000★ページが割り当たる★
 virt:0x55ff0b2cd000, phys:0x72edd0000★ゼロページが外され、別のページが割り当たる★
 virt:0x55ff0b2ce000, phys:(not present)
 virt:0x55ff0b2cf000, phys:0x1cb695000
 virt:0x55ff0b2d0000, phys:(not present)

2番目の (not present) な領域にも書けますし、3番目のゼロページが割り当たっている領域にも書けます。読み出してみても、ちゃんと書けていることがわかります。

書き込んだあとの仮想アドレスと物理アドレスの対応を見ると、2番目はreadした時とは違ってゼロページではなさそうなアドレスが割当たります。3番目はゼロページが外され、別のページが割り当てられます。

不思議に見えるかも知れませんが、ゼロページは0データを返す専門なので、書き込みができません、というかカーネルが書き込みを許しません。ゼロページに書き込もうとした場合はゼロページを外して別のページを割り当て、以降はそのページを使って下さい、という仕組みになっています。

編集者:すずき(2023/04/29 22:02)

コメント一覧

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



link もっと前
2017年7月12日 >>> 2017年7月3日
link もっと後

管理用メニュー

link 記事を新規作成

<2017>
<<<07>>>
------1
2345678
9101112131415
16171819202122
23242526272829
3031-----

最近のコメント5件

  • link 21年3月13日
    すずきさん (03/05 15:13)
    「あー、このプログラムがまずいんですね。ご...」
  • link 21年3月13日
    emkさん (03/05 12:44)
    「キャストでvolatileを外してアクセ...」
  • link 24年1月24日
    すずきさん (02/19 18:37)
    「簡単にできる方法はPowerShellの...」
  • link 24年1月24日
    KKKさん (02/19 02:30)
    「追伸です。\nネットで調べたらマイクロソ...」
  • link 24年1月24日
    KKKさん (02/19 02:25)
    「私もエラーで困ってます\n手動での回復パ...」

最近の記事3件

  • link 24年3月25日
    すずき (03/26 03:20)
    「[Might and Magic Book One TASのその後] 目次: Might and Magicファミコン版以前(...」
  • link 21年10月4日
    すずき (03/26 03:14)
    「[Might and Magicファミコン版 - まとめリンク] 目次: Might and Magicファミコン版TASに挑...」
  • link 24年3月19日
    すずき (03/20 02:52)
    「[モジュラージャックの規格] 古くは電話線で、今だとEthernetで良く見かけるモジュラージャックというコネクタとレセプタク...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
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 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

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

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 03/26 03:20