連載
» 2011年01月13日 00時00分 公開

Androidをデバッグしメモリダンプからデータを復旧する作りながら理解するファイルシステムの仕組み(10)(2/3 ページ)

[森 崇 株式会社 永和システムマネジメント,@IT MONOist]

3.物理オフセットを管理するbuffer_headについて

 ここまでの説明で、pageはメモリ上でファイルデータを管理する構造だということが分かりました。

 しかし、これだけだと、例えばファイルデータを変更した場合、元あった物理ディスクに書き戻すことはできません。つまり、pageが管理するデータが物理ディスク上のどこにあるのかを管理するデータ構造が別に必要となります。そのデータ構造が「buffer_head(バッファーヘッド)」構造体です。ファイルデータとしての管理構造は図7のようになります。


buffer_headによる物理オフセット管理(ブロックサイズが512bytesの場合) 図7 buffer_headによる物理オフセット管理(ブロックサイズが512bytesの場合)

 まず、page構造体の「private」というメンバは、buffer_head構造体をポイントしています。一方、buffer_headにはブロック型デバイスディスクリプタへのポインタ(struct block_device * b_bdev)および、物理オフセット(sector_t b_blocknr)を管理するメンバがあります。また、buffer_headのI/O用バッファは、ページフレームへのアドレスを指すメンバ(char* b_data)で管理しています。これらの情報があれば、「どのデータ(b_data)」を、「どの物理ディスク(b_bdev)」の「どこ(b_blocknr)」にI/O発行するかが一意に決まるわけです。

 buffer_headは、ファイルシステムのブロックサイズ単位で管理されており、tarfsの場合は、ブロックサイズが512bytesですので、1ページ当たり8個のbuffer_headが存在することになります。そのため、ページ内のbuffer_headは、「b_this_page」というメンバを使用して、オフセット順に単方向リスト管理がされています。

メモリダンプを採取してファイルデータを復旧してみよう!

 以上、Linuxカーネルのファイルデータ管理について一通り見てきました。

 それではこの知識を“実践知”として生かすために、早速、組み込みボードをデバッグし、メモリダンプからファイルデータを復旧してみましょう!

 ステップは、以下の4つです(図8)。

今回のステップ 図8 今回のステップ

(1)kgdbとの通信路を確立する

 まずは、ターゲットボードを起動し、その後、ホストPC上で以下のようにgdbを立ち上げます(注8)。

$ prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/arm-eabi-gdb vmlinux 

※注8:「prebuilt」は、Androidプラットフォーム直下のディレクトリです。また、「vmlinux」はLinuxのカーネルイメージです。


 次に、以下の「gdb」コマンドでターゲットボードのkgdbとの通信路を確立します。

(gdb) target remote udp:<ip address>:<port> 
<ip address> ……ターゲットボードのIPアドレス(今回の場合は192.168.2.2)
<port> ……KGDBのポート「6443」固定

 すると、以下のようなメッセージが出力され、Linuxカーネルはgdbからのコマンド実行待ち状態となります。

kgdb_breakpoint () at kernel/kgdb.c:1739
1739            wmb(); /* Sync point before breakpoint */ 

 そして、「c」コマンドを実行し、処理を継続させます。

(gdb) c 

 これで、kgdbとの通信路確立は終了です。後はtarfsをマウントして、init.rcのデータを参照し、メモリ上にキャッシュします。

(2)メモリダンプを採取する

 メモリダンプを採取するには、gdbの「dump」コマンドを使用します。この際、メモリの開始位置と終端位置を指定する必要があります。そこで、今回のターゲットボードのメモリ量を調べるため、/proc/meminfoを参照して、システムのメモリ量を確認してみます。

/ # cat /proc/meminfo
MemTotal:          90572 kB
MemFree:            8692 kB
Buffers:              40 kB
Cached:            33508 kB
SwapCached:            0 kB
        : 

 「MemTotal」から約90Mbytesがシステムのメモリとして使われていることが分かります。よって、dumpコマンドを以下のように実行します。

(gdb) dump memory kernel.dump 0xc0000000 0xc5a00000 
kernel.dump ……ダンプ出力ファイル
0xc0000000 ……カーネルメモリ領域の開始アドレス
0xc5a00000 ……終端アドレスは開始アドレス+90Mbytes分を指定

Copyright © ITmedia, Inc. All Rights Reserved.