2012年3月16日金曜日

system_process以降

第4回横浜PF部の勉強会(init 祭り)においては、Zygoteの非常に複雑な起動の仕組みを紹介しました。ただ、この時点では学習不足もあってZygoteとsystem_processをあまり分けて考えていませんでした。

Zygoteは、/system/bin/app_processを使って起動されるすべてのVMプロセスの親となるプロセスで、起動時にオプション --start-system-serverの引数が渡されると、起動時にsystem_processという名前の子プロセスを生成するように実装されています。

system_processは、Zygoteをコピーして生成されたAndroidの中枢を担うシステム用のVMプロセスで、Java側の各種サービススレッド群は、すべてこのsystem_processのスレッドとして生成されます。

DBMSを使ってスレッドの一覧を取得できます。

*1 59 native 69 37 main
*2 60 vmwait 21 341 HeapWorker
*3 61 vmwait 106 18 GC
*4 62 vmwait 0 0 Signal Catcher
*5 63 running 138 431 JDWP
*6 64 vmwait 76 54 Compiler
7 65 native 1 0 Binder Thread #1
8 66 native 0 0 Binder Thread #2
9 71 native 479 150 android.server.ServerThread
10 72 native 248 311 ActivityManager
11 76 timed-wait 19 21 ProcessStats
12 77 native 16 5 PackageManager
13 78 native 0 0 FileObserver
14 79 native 0 0 AccountManagerService
15 81 native 0 0 SyncHandlerThread
16 86 native 55 10 AlarmManager
17 83 native 0 1 UEventObserver
18 84 native 1 0 PowerManagerService.mScreenOffThread
19 85 native 5 0 PowerManagerService
20 87 native 16 2 WindowManager
21 88 native 706 64 WindowManagerPolicy
22 89 native 1 3 InputDispatcher
23 90 native 2 0 InputReader
24 91 native 4 4 NetdConnector
25 94 native 0 0 WifiService
26 92 native 6 0 ConnectivityThread
27 95 native 0 0 Tethering
28 96 native 0 0 MountService
29 97 native 4 0 VoldConnector
30 99 native 0 0 AudioService
31 101 native 0 0 SoundPool
32 102 native 0 0 SoundPoolThread
33 103 native 0 0 backup
34 107 timed-wait 7 17 watchdog
35 110 native 2 1 LocationManagerService
36 111 native 21 13 ThrottleService
37 122 native 0 0 GpsLocationProvider
38 160 native 0 0 Binder Thread #3
39 163 native 0 0 Binder Thread #4
40 164 native 3 0 Binder Thread #5
42 292 native 0 0 Binder Thread #9
44 231 native 0 0 Binder Thread #8
45 217 native 0 0 Binder Thread #6
46 229 native 0 0 Binder Thread #7
47 293 native 0 0 Binder Thread #10
48 295 native 0 0 Binder Thread #11

結構たくさんのスレッドが立ってますね。

勉強会でも話した内容ですが、ここまでの流れを簡単に述べると

  1. kernelが/initを起動する
  2. /initがinit.rcに従い /system/bin/app_process(Zygote) を --start-system-server引数付きで起動する
  3. app_processがfork後、com.android.server.SystemServer#main を実行する(system_server)
  4. com.android.server.SystemServer#main が android_server_SystemServer_init1(JNIEnv* env, jobject clazz)をJNI経由で呼び出し
  5. android_server_SystemServer_init1() が system_init()を呼び出し
  6. system_init()では Surfaceflingerのinstantiate等を行った後、SystemServer#init2をコールバック
  7. SystemServer#init2が、 amdrpod.server.ServerThreadを生成、runする。
  8. ServerThreadが各種サービス・マネージャー関連を生成、登録していく。それっぽい箇所を抜き出してみると
    • new EntropyService()
    • new PowerManagerService()
    • ActivityManagerService.main()
    • new TelephonyRegistry(context)
    • AttributeCache.init(context)
    • PackageManagerService.main()
    • ActivityManagerService.setSystemProcess()
    • context.getContentResolver()
    • new AccountManagerService(context)
    • ContentService.main()
    • ActivityManagerService.installSystemProviders()
    • new BatteryService(context)
    • new LightsService(context)
    • new VibratorService(context)
    • PowerManagerService#init()
    • new AlarmManagerService(context)
    • Watchdog.getInstance().init()
    • WindowManagerService.main()
    • ((ActivityManagerService)ServiceManager.getService("activity").setWindowManager
    • new BluetoothService(context)
    • new BluetoothA2dpService()
    • new DevicePolicyManagerService(context)
    • new StatusBarManagerService(context)
    • new ClipboardService(context)
    • new InputMethodManagerService()
    • new NetStatService()
    • NetworkManagementService.create()
    • ConnectivityService.getInstance()
    • new ThrottleService(context)
    • new AccessibilityManagerService(context)
    • new MountService(context)
    • new NotificationManagerService()
    • new DeviceStorageMonitorService(context)
    • new LocationManagerService(context)
    • new SearchManagerService(context)
    • new DropBoxManagerService()
    • new WallpaperManagerService(context)
    • new AudioService(context)
    • new HeadsetObserver(context)
    • new DockObserver()
    • new UsbObserver(context)
    • new UiModeManagerService(context)
    • new BackupManagerService(context)
    • new AppWidgetService(context)
    • new RecognitionManagerService(context)
    • new DiskStatsService(context)
    • new AdbSettingsObserver
    • VMRuntime.getRuntime().startJitCompilation()
  9. この後、生成したサービスの一部のsystemReady()メソッドを実行していく
  10. Looper.loop()

とまぁ、こんな処理が長々と一つのメソッドに・・・・長いわ!と途中で放り投げたくなるところでしたけど。余所からアクセスできるようにするものは、ServiceManager#addServiceしています。とりあえずにしておきました。なお、メソッドがstaticか否かまで確かめ切れていないので、色々記載に間違いがある気もしていますが・・・とりあえずメモ書きレベルだということでお許し下さい。

名前からもなんとなく想像がつきますが、Threadは、これらのクラス群の処理の中で生成、runされていくのではないでしょうか。近いうちにこのあたりも追いかけてみたいなと思います。

さて、このsystem_processも重要なのですが、先日psコマンドの一覧をtreeにして日記にあげた通り、他のJavaアプリケーションも、それぞれZygoteを親として生成されたVMプロセスとして動作しています。
  • jp.co.omronsoft.openwnn
  • com.android.phone
  • com.android.systemui
  • com.android.launcher
  • android.process.acore
  • com.android.mms
  • android.process.media
  • com.android.deskclock
  • com.android.email
  • com.android.protips
  • com.android.music
  • com.android.quicksearchbox
ここで気になるのが、第三回の勉強会で @l_b__ さんが疑問視されていた、Javaアプリを起動しているのは誰?という話です。
Zygoteが親なので、fork自体はZygoteプロセスなのでしょうが、誰がどのように起動しているものやら。このあたりも追いかけて次回のPF部のお題にあげたいところだったりします。