2012年01月17日

Androidのadbのメモ(1) adb serverの観察

adbのadb serverの動きをstrace, gdbで観察しました。Android 4.0.3を使用しています。



adbの登場人物

  • adb client
  • adb server
  • adb deamon

上の2つはホスト側で、最後のものはターゲット側で動作します。

Todo: そのうち図を描く。

adb client

adb shell や adb logcat などのadbのコマンドはadb serverを介してターゲットのadbdと通信します。

adb server

adb serverはひとつのホストでひとつだけ動作します。adb serverは必要に応じて起動されますが、起動のみを行う場合は adb start-server を実行します。

adb start-server を実行したときのstraceのログ

一度 adb kill-server でadb serverを止めて、straceのログをファイルに保存するようにしながら、adb start-server を実行します。数秒待ってからコントロールCで止めます。

$ adb kill-server
$ strace -ff -o /tmp/adb_strace adb start-server
[ Process PID=10474 runs in 32 bit mode. ]
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
^C$

これで4つのログファイルが生成されました。

file_adb_strace.10474

file_adb_strace.10475

file_adb_strace.10476

file_adb_strace.10477

10474のプロセスは最初execve "adb start-server" から開始しています。10475のプロセスをforkした後、そのプロセスから"OK"の応答を確認したら"* daemon started successfully *\n"とstdoutに書いて終了しています。

10475のプロセスは最初exeve "adb fork-server server" から開始され、最後はselectで待ち状態になっています。2つのsocketpairと127.0.0.1:5037のポートを待っています。"/tmp/adb.log" にログを書き込みます。

10476は10475のプロセスから生成されたスレッドです。/dev/bun/usb/のディレクトリをポーリングしながら監視しています。

10477も10475のプロセスから生成されたスレッドです。port 5555, 5557, 5559, .. 5585 に接続を試みた後に終了しています。

キーボードからコントロールCを入力してSIGINTのシグナルを発行しましたが、この時点で動作していたのは10475と10476の2つだけでした。

ソースコードと見比べる

このログの結果と system/core/adb のソースコードをつき合わせて推察すると

adb serverをforkしてexecしているのは、adb.c のlaunch-server

10476でUSBのポーリングをしていたスレッドはusb_linux.cのdevice_poll_thread. コメントで /* XXX use inotify */ 確かにポーリングするのは美しくない。ターゲットで/dev/input/以下のデバイスファイルを監視しているところでは確かinotify系のシステムコールが使われていた。

このスレッドはusb_initで生成される。

10477でportをチェックしていたスレッドはtransport_local.cのclient_socket_thread. ここのコメントによれば、すでに動いているemulatorを探すとのこと。このスレッドはlocal_initで生成される。

usb_init, local_initはどちらもadb_mainから呼ばれる。

10475でselectを呼んでいたところは、fdevent.cのfdevent_process

gdbでスタックトレースを確認

ここまであたりをつけてから、gdbで実際にそれを確認してみます。

adb serverを起動してから、そのプロセスにgdbでアタッチしてスタックトレースを確認しました。実際の操作はこちら。gdb_adb_server0.txt

selectで待っているスレッドのスタックトレース

#0 0xf7fdf430 in __kernel_vsyscall ()
#1 0xf7d9aa81 in select () from /lib32/libc.so.6
#2 0x0805f3ea in fdevent_process () at system/core/adb/fdevent.c:378
#3 0x0805fc95 in fdevent_loop () at system/core/adb/fdevent.c:689
#4 0x0804c37b in adb_main (is_daemon=1, server_port=5037)
    at system/core/adb/adb.c:979
#5 0x080538b2 in adb_commandline (argc=0, argv=0xffffcfc8)
    at system/core/adb/commandline.c:915
#6 0x0804b28f in main (argc=3, argv=0xffffcfc4) at system/core/adb/adb.c:1279

USBのポーリングをしているスレッドのスタックトレース

#0 0xf7fdf430 in __kernel_vsyscall ()
#1 0xf7d6b096 in nanosleep () from /lib32/libc.so.6
#2 0xf7d6aec0 in sleep () from /lib32/libc.so.6
#3 0x0805ed24 in device_poll_thread (unused=0x0)
    at system/core/adb/usb_linux.c:666
#4 0xf7f6c96e in start_thread () from /lib32/libpthread.so.0
#5 0xf7da1b5e in clone () from /lib32/libc.so.6

emulatorのポートをチェックするスレッドはすぐに終了してしまうので、このプロセスの最初の段階からgdbで追いかける必要があります。gdbでforkされた子プロセスのほうを追いかけるときは、set follow-fork-mode childとします。実際の操作はこちら。gdb_adb_server1.txt

実際にclient_socket_threadに来て、(void) local_connect(port); をループの中で実行したあとにこの関数をぬけていることが確認できました。

これでadb serverの定常状態ではどこを実行しているのかが理解できました。



トラックバックURL

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード