应用程序进程启动过程
分析的源码基于android-8.0.0_r4
《安卓进阶解密》读书笔记
应用程序进程启动过程
在「Android系统启动」笔记中提到,Zygote
进程中会有一个Server端的Socket,等待AMS请求"创建新的应用程序进程",这里会将「AMS请求」与「Zygote
进程响应,创建应用程序进程」这两部分联系起来。因为应用程序进程由Zygote
进程Fork而来,所以应用程序进程可以获得Zygote
进程在启动时创建的虚拟机实例。
AMS发送请求
时序图如下
- AMS的startProcessLocked方法:获取要创建的应用程序进程的相关信息,作为参数传入下一个方法中
- Process的start方法、ZygoteProcess的start方法:这两个方法没有做什么实际的事情,就是把前面传入的"应用程序进程的相关信息",作为下一个要调用的方法的参数传入
- ZygoteProcess的startViaZygote方法:根据传入的"应用程序进程的相关信息",创建一个名称为
argsForZygote
的ArrayList<String>
,在argsForZygote
里面保存"应用进程的启动参数",最终走到了下面的语句
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
- 这里先看
openZygoteSocketIfNeeded
方法,这里会与ZygoteState
尝试进行connect
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//与Zygote进程建立Socket连接
primaryZygoteState = ZygoteState.connect(mSocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
//连接Zygote主模式返回的ZygoteState是否与启动应用程序进程所需要的ABI匹配
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
//如果不匹配,则尝试连接Zygote辅模式
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
//连接Zygote辅模式返回的ZygoteState是否与启动应用程序进程所需要的ABI匹配
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
这里就是与Zygote
进程的等待AMS请求的Socket
建立连接。Zygote
的启动脚本有4种,如init.zygote64.rc
,就只会有Zygote
主模式;如init.zygote32_64.rc
,就有主模式的Zygote
,也有附模式的Zygote
,所以这里就有了代码中的两次连接操作。
ZygoteProcess
的zygoteSendArgsAndGetResult
方法,在上面的startViaZygote
方法中,先调用openZygoteSocketIfNeeded
尝试与Zygote
进程建立Socket
连接,假如成功建立连接,会返回的ZygoteState
对象,接着会调用zygoteSendArgsAndGetResult
方法并将ZygoteState
对象作为方法参数传入
# zygoteState:与Zygote进程成功建立Socket连接后返回的对象
# args:应用进程的启动参数
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
/**
* See com.android.internal.os.SystemZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
该方法的主要作用是将应用进程的启动参数args
写入ZygoteState
之中,ZygoteState
是ZygoteProcess
的静态内部类,用于表示与Zygote
进程通信的状态,另外,上面的一大段英文注释挺重要的
/**
* See com.android.internal.os.SystemZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
它表示的是与后面「Zygote
接收请求」的一个交互过程,在「AMS发送请求」中,将应用进程的启动参数写入ZygoteState
中,在Zygote
进程中,会在ZygoteConnection
的runOnce
方法中,调用readArgumentList
方法,来读取应用进程的启动参数,在Zygote
进程读取完应用进程的启动参数之后,它会往输出流里面写入"应用进程pid或者-1"、"一个布尔值",接着在AMS这边,会读取这些信息
Zygote接收请求
这里描述的是一个Zygote
接收请求并创建应用程序进程的过程
时序图如下
Fork进程
ZygoteInit
的main、ZygoteServer
的runSelectLoop:在「Android系统启动」笔记中,提到Zygote
进程会通过调用ZygoteServer
的runSelectLoop方法等待AMS的请求,代码如下
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
...
while (true) {
...
for (int i = pollFds.length - 1; i >= 0; --i) {
...
if (i == 0) {
/*
* i==0的时候,说明当前fds里面只有mServerSocker的文件描述符,说明此时
* 没有"创建应用程序进程"的请求,通过acceptCommandPeer方法等待连接
*/
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
/*
* i不等于0,说明这是一个"创建应用程序进程"的请求,通过调用ZygoteConnection
* 的runOnce方法,来创建一个"新的应用程序进程"
*/
boolean done = peers.get(i).runOnce(this);
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
ZygoteConnection
的runOnce:
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//1.获取应用进程的启动参数
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
...
try {
//2.将args包装到parsedArgs对象中
parsedArgs = new Arguments(args);
...
//3.通过fork当前进程,创建应用程序进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal,
parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, fdsToIgnore,
parsedArgs.instructionSet,parsedArgs.appDataDir);
} catch (ErrnoException ex) {
...
}
try {
//4.子进程会执行If(pid == 0)的分支
if (pid == 0) {
// in child
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//5.处理应用程序进程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw Zygote.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
第1步:这里读取到的"应用进程的启动参数",正是「AMS发送请求」笔记中提到的,AMS在zygoteSendArgsAndGetResult
向ZygoteState
写入的"应用进程的启动参数"
抛出异常-清理栈帧
后面的套路就和SystemServer
进程启动时的套路一样了,这里简单说明
ZygoteConnection
的handleChildProc方法:这里会调用到ZygoteInit
的zygoteInit
方法ZygoteInit
的zygoteInit
方法:
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
...
//1.启动Binder线程池
ZygoteInit.nativeZygoteInit();
//2.进入ActivityThread的main方法
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
第1步:关于"启动Binder线程池"这一部分,参数书本P75
- RuntimeInit的
applicationInit
方法:
protected static void applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
...
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
- RuntimeInit的
invokeStaticMain
方法:
# className:android.app.ActivityThread
# argv:应用程序进程的一些启动参数
# classLoader:null
private static void invokeStaticMain(String className, String[] argv, ClassLoader
classLoader) throws Zygote.MethodAndArgsCaller {
Class<?> cl;
try {
//获取android.app.ActivityThread类
cl = Class.forName(className, true, classLoader);
} ...
Method m;
try {
//获取ActivityThread的main方法
m = cl.getMethod("main", new Class[] { String[].class });
} ...
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new Zygote.MethodAndArgsCaller(m, argv);
}
这里的抛出异常-清理栈帧的套路和SystemServer
进程启动时的套路是一样的,这样做的理由在「SystemServer进程启动过程」中已经详细说明,这里不再赘述,最终会在ZygoteInit
的main
方法捕获异常,调用MethodAndArgsCaller
的run
方法,接着会调用到ActivityThread
的main
方法,到了这里,应用程序进程就创建完成了并且运行了主线程的管理类ActivityThread
补充几点
MethodAndArgsCaller
是Zygote.java
的静态内部类ActivityThread
:这是应用程序主线程的管理类
ActivityThread.main
看一下ActivityThread
的main
方法
# args:应用程序进程的一些启动参数
public static void main(String[] args) {
...
//1.创建主线程Looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
//2.若Handler类型的sMainThreadHandler为null
if (sMainThreadHandler == null) {
//3.获取H类并赋值给sMainThreadHandler
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//4.Looper开始工作
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
H类:H类继承至Handler,是ActivityThread
的内部类,用于处理主线程的消息循环
参考
《安卓进阶解密》