[翻訳] Androidの起動工程

twitterでAndroidの起動に関する文章が紹介されていました。
http://www.huomo.cn/developer/article-b95a.html(中文)

なかなか良い資料だったのでざっくり翻訳してみました。
中文と途中から英文でしたが、何とか大意は取れました。
↓以下は中国語で火魔网の記事を翻訳しましたという説明(念のため)
--------------------中文--------------------------
你好,这个文件不是我写的,翻译成而已。
原文是火魔网(www.huomo.cn)的[android启动流程]
http://www.huomo.cn/developer/article-b95a.html
这个文件的内容很好,我想给日本朋友介绍一下。
所以翻译成日语。
--------------------------------------------------



Androidの起動工程

●SystemServerの起動
frameworks/base/services/java/com/android/server/SystemServer.java: run()
その中で、ActivityManagerService.installSystemProviders()を使用します。
最後には、frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/配下の
各content providersのonCreate()関数を使用して、データベースの内容を初期化します。
画像


other ref:http://www.cnblogs.com/jacktu/archive/2010/07/02/1769939.html

AndroidはLinuxシステム起動の4つの手順からなります。

(1) initの起動

(2) Nativeサービスの起動

(3) System Server,Androidサービスの起動

(4) Homeの起動

全体の起動の枠組みは図のようになります。

画像


・第一歩:initial工程(system\core\init)
initを実行します。initはカーネルが起動するユーザプログラムの1つです。
カーネルが自分で起動(既に搭載されたメモリ、運行開始、さらに既に初期化された全てのプログラム、データベースなど)の後、1つのユーザプログラムinitの起動を通じて、工程の完了を導きます。initは第一番目の工程です。

Init.rc

Init.marvell.rc
画像


Initはinit.rcとinit.xxx.rcスクリプトにより、いくつかの基本的なサービスを起動します。

servicemanamger
zygote
。。。

最後にInitは終了しないだけでなく、さらにproperty serviceの機能を担当します。

1.1スクリプトファイル
init@System/Core/Init

Init.c: parse_config_file(Init.rc)

@parse_config_file(Init.marvel.rc)

スクリプトファイルの解析:Init.rcとInit.xxxx.rc(ハードウエアプラットフォームに応じて)

Init.rcはAndroidが自分で規定した初期化スクリプトです(Android Init Language, System/Core/Init/readme.txt)

そのスクリプトは4つのタイプがあります。

Actions
Commands
Services
Options.

1.2 サービス起動のメカニズム
Initがどのようにrcファイルを解析してサービスを始めるのか見てみましょう。

(1)rcファイルをオープンして、ファイルの内容を解析@ system\core\init\init.c

serviceの情報をservice_listに格納します。@ system\core\init parser.c

(2)restart_service()@ system\core\init\init.c

service_start

execve(…).serviceプログラムの起動。

・第二歩 Zygote
ServicemanagerとzygoteはAndroidの基礎を決定します。Zygoteこのプログラムによって、真のAndroid実行空間を獲得します。
初期化されたサービスは全てNavtive serviceでrcスクリプトファイル中のzygoteの記述です。

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

そのため、Zygoteはmain(…)@frameworks\base\cmds\app_process\app_main.cppから開始します。

(1) main(…)@frameworks\base\cmds\app_process\app_main.cpp

Java Runtimeの開始
runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);
(2) runtime.start@frameworks/base/core/jni/AndroidRuntime.cpp

仮想マシンの起動:startVM(...)
com.android.internal.os.ZygoteInit:main関数の実行
(3)main()@com.android.internal.os.ZygoteInit//本当のZygote。

registerZygoteSocket();//Listenソケットの登録
startSystemServer();
Zygoteサービスフレームワークに入ります。
このいくつかの手順を通して、Zygoteの起動がうまくいけば、Socket通信を利用してActivityManangerServiceの要求を受け取って、アプリケーションプログラムをForkします。

・第三歩 System Server
1つのプログラムのforkにおいて:com.android.server.SystemServer.つまりSystemServer@(SystemServer.java)が実行されます。
Androidの全てのサービス、循環フレームワーク?はSystemServer@(SystemServer.java)上で実行されます。
SystemServer.javaにおいて循環構造は見えません、init2の実現関数のみが見えます、サービスを実行し、さらにAddServiceによってservice Managerにアクセスします。

main() @ com/android/server/SystemServer

init1();

Init1()はNative空間で実現されています(com_andoird_server_systemServer.cpp)。この関数は見ればすぐ分かります。init1->system_init() @System_init.cpp

system_init()において、循環を閉じるための管理フレームワークを見ることが出来ます。

Call "com/android/server/SystemServer", "init2"

…..

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

init2()@SystemServer.javaの中でAndroidの全ての必要とするサービスを実行します。

このinit2()はNew ServiceとAddServiceによってサービスを起動します。

・第4歩 Home起動
後半において、システムが全てのAndroidサービスの起動が完了するところを見ることが出来ます、このような一連の動作によって

(1)xxx.systemReady()を使用して各サービスに準備完了を通知

(2)ActivityManagerService.systemReadyに対しては特別です

Widget.wallpaper,imm(インプットメソッド)等のready通知。

HomeはActivityManagerService.systemReady()の通知の過程で実行します。下のActivityManagerService.systemReady()の仮ソースコードです。

systemReady()@ActivityManagerService.java

resumeTopActivityLocked()

startHomeActivityLocked();//もし第1の起動がHomeActivityであれば

startActivityLocked(。。。)CATEGORY_HOME android起動の工程
このトピックにおいて、Androidのプロセス管理に関してのいくつかの情報を学ぶことが出来る。最初にAndroidのブートを通じてプロセスの起動を見てみましょう。

USER PID PPID VSIZE RSS WCHAN PC NAME

root 1 0 264 176 c00acc6c 0000c36c S /init

root 28 1 724 308 c0051354 afe0c4cc S /system/bin/sh

system 30 1 796 248 c026516c afe0b74c S /system/bin/servicemanager

root 31 1 1824 316 ffffffff afe0b50c S /system/bin/mountd

root 32 1 652 248 c02976e0 afe0c0bc S /system/bin/debuggerd

radio 33 1 5344 664 ffffffff afe0bdbc S /system/bin/rild

root 34 1 71028 18828 c00ad308 afe0b874 S zygote

media 37 1 16812 3456 ffffffff afe0b74c S /system/bin/mediaserver

root 39 1 788 288 c02f9ae4 afe0b50c S /system/bin/installd

system 86 34 187756 21836 ffffffff afe0b74c S system_server

radio 118 34 103476 13896 ffffffff afe0c824 S com.android.phone

app_4 124 34 117848 19248 ffffffff afe0c824 S android.process.acore

app_5 139 34 98672 11516 ffffffff afe0c824 S com.android.mms

app_3 151 34 92096 10976 ffffffff afe0c824 S com.android.alarmclock

app_6 161 34 94436 12616 ffffffff afe0c824 S com.android.calendar

app_9 173 34 93248 11728 ffffffff afe0c824 S android.process.media

app_15 182 34 91848 9764 ffffffff afe0c824 S com.android.voicedialer

app_16 190 34 94524 10812 ffffffff afe0c824 S android.process.im

これらは3種類に分けることが出来ます。

(1)Root Process
initはカーネルがブートした後の最初のプロセスです。主な仕事は以下を実行することです。

・init.rcとinit.%hardware%.rcを解析して実行する
・/dev配下のデバイスノードを自動的に生成する
・ログサービス、プロパティサービスを開始する
・デバイスのためにプロパティを設定する、そして子プロセスの終了イベントを監視する

(2)Native Application Process
init.rcにより、initは以下のネイティブアプリケーションプロセスをforkする

console: シェルをスタートする

servicemanager: binder IPC service managerを起動する

mountd: もし起動後、いずれかのファイルシステムへローカルソケットを通じてコマンドを受信したら、/system/etc/mountd.confで定義された全てのファイルシステムをマウントする。

debuggerd: debug systemを開始する

rild: radio interface layer daemonを開始する

zygote: Android Java VM Runtimeとsystem serverを開始する. これらは最も重要なプロセスです

mediaserver: AudioFlinger, MediaPlayerService, CameraServiceを開始する.

installd: install package daemonを開始する

(3)JAVA Application Process
全てのJavaアプリケーションプロセスはzygoteプロセスからForkされます。system_serverは特別なJavaプロセスで、zygoteから直接Forkされます。
その他のJavaプロセスはActivityManagerService(system_serverプロセス上で実行)から生成されます。例えばこのように

int pid = Process.start("android.app.ActivityThread",

mSimpleProcessManagement ? app.processName : null, uid, uid,

gids, ((app.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0), null);

Process.javaがzygoteと通信する間はUNIXドメインソケットを使用します。全体像を以下の図に示します。

画像


System Server
zygoteによって起動される最初のJavaアプリケーションです。System Serverは、コアとなるAndroidサービスを開始します、例えばActivityManager, WindowManager, PackageManagerなどなど。System ServerはAndroidのコアエンジンです。

Persistent Application(永続的アプリケーション)
ブート中にActivityManagerService.systemReadyは、全ての永続的アプリケーションを開始します。

List apps = ActivityThread.getPackageManager().

getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);

if (apps != null) {

int N = apps.size();

int i;

for (i=0; i

そのため、ブート中はphone applicationのみが自動的に起動されます。それは"com.android.phone”プロセスです。

The First Activity
最初のアクティビティはActivityManagerServiceからIntent.CATEGORY_HOMEインテントを送信することで起動されます。

Intent intent = new Intent(

mTopAction,

mTopData != null ? Uri.parse(mTopData) : null);

intent.setComponent(mTopComponent);

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

intent.addCategory(Intent.CATEGORY_HOME);

}

ActivityInfo aInfo =

intent.resolveActivityInfo(mContext.getPackageManager(),

PackageManager.GET_SHARED_LIBRARY_FILES);

if (aInfo != null) {

intent.setComponent(new ComponentName(

aInfo.applicationInfo.packageName, aInfo.name));

// Don't do this if the home app is currently being

// instrumented.

ProcessRecord app = getProcessRecordLocked(aInfo.processName,

aInfo.applicationInfo.uid);

if (app == null || app.instrumentationClass == null) {

intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);

startActivityLocked(null, intent, null, null, 0, aInfo,

null, null, 0, 0, 0, false);

}

それは、“android.process.acore”プロセスです。(プロセス名は、AndroidManifest.xmlに定義されています)

ブート後に自動起動されるアプリケーション
ActivityManagerService内でアクティビティのアイドルが決定したとき、ActivityManagerServiceは最初にACTION_BOOT_COMPLETEDインテントをブロードキャストします。

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

// Tell anyone interested that we are done booting!

synchronized (this) {

broadcastIntentLocked(null, null,

new Intent(Intent.ACTION_BOOT_COMPLETED, null),

null, null, 0, null, null,

android.Manifest.permission.RECEIVE_BOOT_COMPLETED,

false, false, MY_PID, Process.SYSTEM_UID);

}

現在、MMS, AlarmClock, Calendar, MediaProvider, VoiceDialer と IMがACTION_BOOT_COMPLETEDインテントのレシーバとしてAndroidManifest.xmlに登録されています。そのため、それらのは自動的に起動されます。(これはJavaプロセスが残ることを意味します)

EmailもACTION_BOOT_COMPLETEDのレシーバとしてAndroidManifest.xmlに登録されています。しかし、android:enable=”false”と定義されているので起動しません。






















DownloadProviderもACTION_BOOT_COMPLETEDのレシーバとしてAndroidManifest.xmlに登録されています。しかし、android:enable=”false”と定義されているので起動しません。












Javaプロセスの背後
system_serverは特別な事例です。system_serverはActivityThread.javaのsystemMain static functionを呼び出します、それはActivityThreadのインスタンスを生成します。
ActivityThreadはそれから、アプリケーションスレッド、アプリケーション、アプリケーションコンテキストのインスタンスを生成します、

その他の全てのJavaプロセスは、異なった方法で動作します。それはzygoteにより、Forkされたsystem_serverによって制御されます。
system_server以外のいずれかのJavaプロセスがzygoteからForkされた時、そのJavaプロセスは、自動的にActivityThread.javaのmain static functionを呼び出します(Process.javaと以下のコードの切れ端を見てください)

try {

ZygoteInit.invokeStaticMain(cloader, className, mainArgs);

} catch (RuntimeException ex) {

logAndPrintError (newStderr, "Error starting. ", ex);

}


ActivityThread.javaのmain関数は、ActivityThreadのインスタンスを生成します。ActivityThreadはそれから、ApplicationThreadのインスタンスを生成します。
ApplicationThreadはsystem_server内のActivityManagerServiceと共に情報を交換するためのIBinder objectとして動作します。
新しいプロセスは、この時は、system_serverからのIPCコールの待ちうけ以外何もしません。
アプリケーションとアプリケーションコンテキストは、この段階では生成されません。事実、プロセスが本当に動作するときまで延期されます、
例えば、アクティビティの開始、インテントの受信あるいはサービスの開始などなど

例えば、アクティビティが開始するとき、ActivityManagerServiceはどのプロセスが開始するべきか知っています、
そのためRPCはそのプロセス内で新しいアクティビティを起動するために、ApplicationThreadのscheduleLaunchActivityを呼び出します。
ApplicationThreadはそれから、ActivityThreadに対してアクティビティを起動する必要があることを知らせるためにメッセージを送信します。
ActivityThreadはそれからアプリケーションとアプリケーションコンテキストを生成します。その後、Instrumentationを呼び出します。
Instrumentationはそれから、最後に、本当にアクティビティのJavaオブジェクトを生成するためにJAVA dalvik VMを呼び出します。

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 0

この記事へのコメント

この記事へのトラックバック