2012年10月19日金曜日

StevGuo系列文章翻译之Talking about Android process

通过这个篇文章,我们会了解关于Android进程管理的相关信息。首先我们看一下Android完成boot后加载的进程:
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
我们分几部分来说。

Root进程。
Init是内核booting后的第一个进程。它的主要任务是:
1、 解析并执行init.rc和init.%hardware%.rc。
2、 自动生成/dev下的设备节点。
3、 开户log和property服务。
4、 监视设备、property set以及子进程退出事件。
5、 Native Application进程。

通过init.rc,init会fork出下面的native application进程:
Console:启动shell
ServiceManager:开启binder IPC Service Manager.
Mountd:挂载/system/etc/mountd.conf中定义的fs,接收本地socket中挂载任意fs的命令。
Debuggerd:开启debug系统。
Rild:开启radio接口层的daemon。
Zygote:启动Android的Java VM Runtime和系统服务。它是最重要的进程。
Mediaserver:开启AudioFlinger、MediaPlayerService和CameraService。
Installd:开启安装包的daemon。

Java Application进程
每一个Java Application进程都是从zygote进程中fork出来的。System_server是一个特殊Java 进程,它直接从zygote进程中fork出来,而其它的Java进程是从ActivityManagerService中创建的。ActivityManagerService是运行在system_server进程中的。ActivityManagerService创建Java进程的过程就像下面描述的这样:
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, ((app.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0), null);
而Process.java是使用UNIX domain socket与zygote通信的。

System Server
它是第一个被zygote加载的Java application。它开启Android最核心的服务:
ActivityManager,WindowManager,PackageManager等。因此,它是Android系统启动的源头。

Persistent Application
在booting期间,ActivityManagerService.systemReady会启动下面这些Persistent
Application.
List apps = ActivityThread.getPackageManager().
getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android")) {
addAppLocked(info);
}
}
}
现在只有Phone application被注册为persistent application。注册方式是在AndroidManifest.xml中:
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/dialerIconLabel"
android:icon="@drawable/ic_launcher_phone">
(大兵注:android:persistent属性为true表示这个application在任何时候都应该运行,一旦它被意外强行中止,系统会立即重启。而false则表示这是一个一般的应用程序,通常只有一少部分系统程序应该标记为true。
这样,在booting过程中,只有phone application被自动加载。这就是前面进程列表中我们看到的com.android.phone进程。)

第一个Activity
第一个Activity是通过从ActivityManagerService中发送含有Intent.CATEGORY_HOME的Intent来launch的。
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中.

Booting后被自动加载的程序
当ActivityManagerService检测到activity idle时,它会广播含有ACTION_BOOT_COMPLETED的Intent。
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的Receiver。所以它们都会被自动加载。
Email也注册了,但是它还有另外一个属性android:enable="false",所以它不会被加载。
<receiver android:name=".service.BootReceiver"
android:enabled="false"
>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DEVICE_STORAGE_OK" />
</intent-filter>
</receiver>
(大兵注:android:exported属性表示这个Receiver是否接收外部发送的Intent,如果是true的话表示可以,如果是false,那么这个Receiver只能接收两种来源的消息,自己所属的application或者那些有相同user ID的application。如果这个Receiver中不含有任何fileters,那么它就只能接收含有明确Receiver类名的Intent,意味着这个Receiver只是在application内部使用。这时,默认值就是false。只要有一个filter指明这个Receiver接收来自系统或者其它application的intent,那么默认值就是true.如果想控制Receiver的暴露性,这个属性不是唯一的手段,可以看一下<receiver>的android:permission)

Java进程的背后
System_server是一个特例。它可以调用ActivityThread.java的systemMain静态方法,这个方法会创建一个ActivityThread实例。然后,这个ActivityThread实例就会创建一个ApplicationThread,Application,ApplicationContext实例。
其它的java进程,工作的方式各自不同,都由zygote来fork但由system_server控制。除了system_server外的任何一个java进程被fork时,都会自动调用ActivityThread.java的main方法,可以看一下Process.java或者下面这个代码段:
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError (newStderr, "Error starting. ", ex);
}
ApplicationThread会用Ibinder机制与system_server中的ActivityManagerService交互。这个新进程会等待来自system_server的调用。而Application和ApplicationContext不会在这时被创建,在进程真正工作的时候才被创建。
例如,当开启一个activity时,ActivityManagerService知道这个activity应该运行在哪个进程,所以它会通过RPC机制调用ApplicationThread的scheduleLaunchActivity方法来在那个进程中加载这个新的activity。然后,ApplicationThread会post一个message来让ActivityThread知道它需要开启一个activity。然后,ActivityThread会创建Application和ApplicationContext对象并调用Instrumentation,最后Instrumentation调用Java dalvik VM真正创建一个activity的java对象。

0 件のコメント:

コメントを投稿