一、进程启动方式
在Android系统启动的时候,一些核心进程是由init进程fork出来,比如media、SurfaceFlinger、Zygote等,而另外一些系统核心服务进程则是由Zygote进程fork出来,比如我们的SystemServer进程,在这里面启动AMS,PMS等。那么对于进程的启动方式fork有哪几种方式?
一般情况下分为两种,fork 带execve和不带execve,有什么 区别?如果是不带execve那么沿用的是父进程的资源。如果是带了execve则重新向系统申请资源。
因此,Android系统中有很多个应用,当这些应用程序进程需要启动的时候需要使用fork execve的方式,也就是说每个应用程序进程都需要自己向Android系统申请独立的资源。
二、应用程序进程启动的原理
在Android系统中,实际上我们是找不到启动进程的接口,对于应用程序来讲,进程的启动是被动的,即在Framework中,当某个组件需要启动的时候,系统会对该组件所依赖的进程进行检测,查看该进程是否已经启动通过getProcessRecordLocked函数来检测,如果已经 启动,则启动真的组件然后返回,否则通过调用AMS中的startProcessLocked(porcessName)来启动进程。伪代码块如下:
在com.android.server.am.ActivityStackSupervisor.java中
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
//app.thread为应用的AMS binder句柄,实际上AMS也会持有一个应用的binder句柄,构成一个双向调用,因为有时候应用需要应用与AMS进行通信。这个双向句柄是由应用启动的时候向AMS打报告并注册生成
if (app != null && app.thread != null) {
//启动组件
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
//启动进程,实际上是调用AMS中的
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
由于SystemServer进程也会有Loop循环,处理自己的消息,当AMS需要启动应用程序进程的时候,则向SystemService发送消息,具体是在AMS的handleProcessStartedLocked函数中进行,代码如下:
private boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
long expectedStartSeq, boolean procAttached) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
//发送消息,由SystemServer进程的Loop循环处理消息,执行runOnce函数,进而启动对应的入口函数main,这里是ActivityThread.main()
mHandler.sendMessageDelayed(msg, usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
return true;
}
在android.app.ActivityThread.java中的main函数核心代码如下,从这里我们可以得知App中Application中的onAttachBaseContext方法是在什么时候被调用起来的。
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
//获取AMS的Binder对象,向AMS报告,说明应用程序已经启动好
//IActivityManager mgr = ActivityManager.getService();
//mgr.attachApplication(mAppThread, startSeq);
//实际上就是我们App中Application的onAttachBaseContext方法被调用
thread.attach(false);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
这也就是为什么有多少个子进程,Application中的生命周期会被调用多少次的原因。
当某个组件启动的时候,会从一个进程Record中获取该进程,如果获取不到则说明进程没有启动,即ApplicationInfo对象为null,如果获取到ApplicationInfo.thread为null,说明该进程启动后还没有向AMS打报告注册,此时进程向AMS注册。否则开始AMS的startProcessLock函数启动进程,如上代码块说明。
实际上一个应用程序进程的启动就是遵循Android的进程启动时的Loop机制,通过Zygote进程fork出来,在ZygoteConnnection中的runOnce()函数中走下去,最终调用到ActivityThread的main入口函数,进程启动。