当点击Launcher主界面的一个应用程序图标时,如果这个应用程序还未曾启动,就会被启动。而判断应用程序有没有启动和去启动应用程序都由核心服务AMS来做,它的startProcessLocked()方法会真正地启动应用程序子进程。而启动应用就是创建一个应用进程,这个工作是由Zygote来fork完成的。
下面为AMS的startProcessLocked()方法:
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
......
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
......
ProcessStartResult startResult;
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith, entryPointArgs);
}
.......
}
AMS的startProcessLocked()方法调用Process类的start()方法为应用程序创建新的进程,这里的参数entryPoint为“android.app.ActivityThread”,它是传进去的第一个参数,也就是程序初始化进程时要加载的主文件Java类。当应用进程启动之后,会把这个类加载到进程,调用它的main()方法作为应用程序进程的入口。
Process类的start()直接调用了ZygoteProcess类的start()方法,该start()方法有直接调用了ZygoteProcess类的startViaZygote()方法,下面看看该方法实现:
private Process.ProcessStartResult startViaZygote(final String processClass,final String niceName,final int uid, final int gid,final int[] gids,int runtimeFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,String instructionSet,String appDataDir,String invokeWith,String[] extraArgs)throws ZygoteStartFailedEx {
ArrayList argsForZygote = new ArrayList();
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
......
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
首先给它设置值,包括uid、gid等。这些值是应用程序在安装时系统分配好的。接着调用openZygoteSocketIfNeeded()方法来链接“zygote”Socket,链接Socket成功之后,就会调用zygoteSendArgsAndGetResult()方法来进一步处理。
先来看看openZygoteSocketIfNeeded()方法:
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
.......
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(mSocket);
}
.......
}
方法中的mSocket的值是“zygote”,通过connect()方法去链接“zygote”Socket。
接着看看zygoteSendArgsAndGetResult()方法:
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList args)
throws ZygoteStartFailedEx {
try {
........
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();
.......
}
通过Socket写入流writer把前面传过来的那些参数写进去,Socket即ZygoteServer类的runSelectLoop()方法监听。写入这些数据之后,ZygoteServer类的runSelectLoop()方法就能被监听到。
看一下runSelectLoop()方法的关键实现代码:
Runnable runSelectLoop(String abiList) {
.......
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
......
}
进入ZygoteConnection类的processOneCommand()方法后:
Runnable processOneCommand(ZygoteServer zygoteServer) {
........
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd);
........
}
之前启动SystemServer进程的代码有点相似。此处是通过Zygote.forkAndSpecialize()来fork新的应用进程,而启动systemserver进程是通过Zygote.forkSystemServer()来fork SystemServer进程。这里通过handleChildProc()方法处理,而之前是嗲偶用handleSystemServerProcess()来处理。通过fork新的应用程序进程之后,返回pid等于0就表示进入子进程,于是调用handleChildProc()方法进一步处理:
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd) {
........
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
.......
}
到此处,后面便和创建SystemServer进程是一样的了,唯一不同的是,SystemServer进程启动之后进入的是主类SystemServer.java的main()函数,而这里应用程序启动起来后进入的是主类是ActivityThread.java的main()函数。
至此我们总结梳理一下:
Zygote进程以及Zygote进程启动SystemServer进程和启动应用程序进程就分析完毕了,Zygote进程为了启动SystemServer和启动应用程序进程主要做了两件事,一是初始化Binder驱动用来进行进程间通信,二是通过反射进入main()方法。