それでは、先ほどコンパイルしたカーネルモジュールを使用して、Androidを起動してみましょう。
要領は以下のとおりです。
$ cd ${HOME}/mydroid $ android-sdk-linux_86/tools/emulator -kernel common/arch/arm/boot/zImage @androidDev -qemu -s
emulatorコマンドの引数にあるオプションの意味は、以下のとおりです(表3)。
オプション | 意味 | |
---|---|---|
-kernel | AndroidエミュレータのLinuxカーネルを指定する | |
@ | 仮想デバイス名を指定する | |
-qemu -s | gdbとの通信用ポート(1234)を開く | |
表3 emulatorコマンドの引数にあるオプションの意味 |
うまくAndroidが起動できました。それでは、まず画面下のタブをクリックし、「Dev Tools」−「Terminal Emulator」を選択して、コマンドライン上でAndroid環境を確認してみましょう。
図7は、ターミナル上で以下のコマンドを実行した結果です。
$ ls -l $ mount
lsの実行結果から、ルート(/)直下には、17個のファイルがあることが分かります。PC Linuxとはだいぶディレクトリ構成は違うようです。特に興味深いのは、「sdcard」というディレクトリがあることです。これは、Android端末のSDカードがマウントされるディレクトリになります。
さて、気になるAndroidエミュレータで採用されているファイルシステムですが、引数なしでmountコマンドを実行すればその一覧を見ることができます。このうち永続化可能なものとしては、「/sdcard」のvfatと「/system」などのyaffs2があります。
vfatはWindows用のファイルシステムで、SDカードで使われるファイルシステムですね。一方、yaffs2はNAND専用のファイルシステムです。PC Linuxのファイルシステムの場合、HDDのファイルシステムはext3かext4ですが、携帯端末の場合は、HDDだと衝撃に弱いため、NANDなどのフラッシュメモリが使われている場合が多いです。このため、そのファイルシステムも特殊なものを使用する必要があります(yaffs2はその1つなのですね)。
それでは、以下のコマンドを実行し、Linuxカーネルのデバッグをしましょう。
$ cd ${HOME}/mydroid/common $ ddd --debugger ../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-gdb
dddは、“Data Display Debugger”の略で、--debuggerで指定したgdbコマンドをGUI上で操作するためのコマンドです。図8は、dddの初期画面であり、大きく分けて3つの枠があります。1番上はグラフィック表示用のもので、真中がソース表示用、1番下がgdbコマンド実行用のものです。
それでは、以下の要領でgdbコマンドを実行し、デバッグの準備をしましょう。
(gdb) target remote localhost:1234 ……Androidエミュレータのgdbポート(1234)に接続する (gdb) file vmlinux ……gdbにLinuxカーネルイメージを認識させる (gdb) b vfs_statfs ……Linuxカーネルの関数vfs_stafs()にブレイクを張る (gdb) c ……Linuxカーネルの処理を継続させる
次に、Androidのターミナル上で、dfコマンドを実行してみます。すると、dfコマンドの延長で実行されるvfs_statfs()というカーネル関数で処理が止まり、図9のように表示されます。
この関数では、44行目のdentry->d_sb->s_op->statfs(dentry,buf)を実行している個所が重要であり、dentryという変数からstatfs()という関数ポインタのコールが行われていることが分かります。このdentryという変数は、Linuxカーネル内でファイル名を管理する共通データであり、ここからファイルシステム固有の処理(今回の場合はstatfs())を呼び出すことができる構造になっています。そして、statfs()呼び出し完了後には、bufというデータにdfで表示すべき情報が設定されるようになります。
それでは、ステップ実行で45行目まで実行し、dentryおよびbufデータの中を表示してみましょう。
まず、dentryデータのd_nameというメンバを見てみると(図10)、“/”というファイル名があるのが分かります。つまり、このdentryはルートディレクトリを表しているのです。次に、bufの中をのぞいてみると、特徴的なものとして、f_bsizeが4096bytesで、f_namelenが255となっていますね。f_bsizeは、ファイルシステムのブロックサイズで、f_namelenはこのファイルシステムの最大のファイル名長です。
このように、カーネルのデバッグができるようになればLinuxカーネル内のすべてのデータを参照できるようになります。また、通常のアプリケーションのデバッグと同様に、変数の値を書き換えてしまうこともできます。興味のある方は、ぜひ、カーネルの中を探検してみてください。
次回は、Linuxカーネルのファイルシステム・データ構造の概要を解説し、自分が書いたデータがカーネル内のどこにあるのかを確かめていきます。お楽しみに!(次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.