考察内容:
- 了解Linux下进各启动的方式
- 熟悉应用进程启动的基本流程
- 深入理解应用进程启动的原理
进程启动方式
- 用fork()函数创建子进程后,在子进程的分支直接进入进程处理入口函数
- 在子进程的分支调用execvx(path) 启动另一个可执行文件
应用进程启动原理
- 什么时候触发的进程启动?谁发起的?
- 进程是谁启动的?怎么启动的?
什么时候触发的进程启动?
在启动组件的时候,如果发现组件所在的进程没有启动才发起进程启动。
ProcessRecord app getESSRecordLocked(...);
if(app != null && app.thread != null){
//进程已经启动了,这里可以启动组件了
return;
}
start.processName;
应用进程入口函数:
public static void main(String[] args){
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(flase); //内部将调用attachApplicationLocked()
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在启动Service为例:应用要启动Service,这个请求会发到AMS,AMS最终会调用bringUpServiceLocked函数
String bringUpServiceLocked(ServiceRecord r, String procName,){
//根据进程名称查找ProcessRecord
ProcessRecord app = mAm.getProcessRecordLocked(procName);
if(app != null && app.thread != null){
//进程已经启动
realStartServiceLocked(r, app, execLnFg);
return null;
}
if(app == null){
//表示进程还没启动
app = mAm.startProcessLocked(procName, ...);
}
if(!mPendingServices.contains(r)){
//把要启动的Service挂起,等进程启动后再继续,见attachApplicationLocked
mPendingServices.add(r);
}
return null;
}
boolean attachApplicationLocked(ProcessRecord proc, String processName){
if(mPendingServices.size() > 0){
ServiceRecord sr = null;
for(int i=0; i < mPendingServices.size(); i++){
sr = mPendingServices.get(i);
mPendingServices.remove(i);
i--;
realStartServiceLocked(sr, proc, sr.createdFromFg);
}
}
}
进程是怎么启动的?
启动进程是在AMS中的startProcessLocked函数
- 打开本地socket (通过openZygoteSocketIfNeeded
- 发送参数列表 (zygoteSendArgsAndGetResult)
- 返回创建的进程ID
Zygote中的处理:
- 读取socket发过来的参数列表
- 用这些参数创建进程
- 父进程通过socket把结果写回去
- 子进程 执行一个Java类的入口函数,类名是AMS通过Socket发过来的,其实就是"ActivityThread"
课堂作业:
- 为什么是zygote来创建里程,是systemServer
- AMS和zygote为什么不用BInder通信?
回归:你知道应用进程是怎么启动的吗?
- 应用进程是什么时候启动的?
- 由AMS向zygote发起的,通过socket通信
- zygote for出应用进程,执行ActivityThread的main函数
- 进程启动之后向AMS报告,整个启动才算结束