4.4 zygote分裂
在Android 的zygote的总结中有提到过,zygote分裂出嫡长子system_server后。假设通runSelectLoopMode等待并处理来自客户端的消息,那么,谁会向zhgote发消息呢?这里以一个Activity的启动为例,具体分析zygote是如何分裂的。
4.4.1 ActivityMannagerServer发送请求
ActivityMannagerServer是由SystemServer创建的。假设通过startActivity来启动一个新的Activity,而这个Activity附属于一个还未启动的进程,那么这个进程该如何启动呢?先来看看ActivityMannagerServer中的startProcessLocked函数,代码如下所示:
【-->ActivityMannagerService.java】
private final void startProcessLocked(ProcessRecord app,String hostingType,String hostingNameStr){
....//这个ActivityMannagerService类很复杂,有14657行!!!
if(“1”.equals(SystemProperties.get("debug.checkjni"))){
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
if("1").equals(SystemProperties.get("debug.assert")){
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
//这个Process类是Android提供的,并非JDK中的Process类。
int pid = Process.start("android.app.ActivityThread",mSimpleProcessManagement ? app.procvessName : null,uid,uid,gids,debugFlags,null);
.......
}
接下来看看Process的start函数,这个Process类是android.os.Process,它的代码在Process.java中,代码如下所示:
【-->Process.java】
public static final int start(final String processClass,final String niceName,ing uid,ing gid,ing[] gids,int debugFlags,String[] zygoteArgs){
//注意,processClass的值是“android.app.ActivityThread”。
if(suportsProcesses){
try{
//调用startViazygote。
return startViaZygote(processClass,niceName,uid,gid,gids,debugFlags,zygoteArgs);
}
}
}
【-->Process.java::startViaZygote()】
private static int startViaZygote(final String processClass,final String niceName,final int uid,final ing gid,final ing[] gids,ing debugFlags String[] extraArgs)thows ZygoteStartFailedEx{
.....//一些参数的处理,最后调用zygoteSendArgsAndGetPid函数。
argsForZygote.add("--runtime--init");//这个参数很重要。
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--runtime=" + gid);
pid = zygoteSendArgsAndGetPid(argsForZygote);
return pid;
}
【-->Process.java::zygoteSendArgsAndGetPid】
private static int zygoteSendArgsAndGetPid(ArrayList<String> args)throws ZygoteStartFailedEx{
int pid;
//openZygoteSocketIfNeeded?是不是打开了和Zygote通信的Socket?
openZygoteSocketIfNeeded();
try{
把请求参数发到Zygote
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.newLine();
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
//读取Zygote处理完的结果,便可得知是某个通信的pid!
sZygoteWriter.flush();
pid = sZygoteInputStream.readInt();
return pid;
}
【-->Process.java】
private static void openZygoteSocketIfNeeded() throws ZygoteStartFailedEx{
try{
sZygoteSocket = new LocalSocket();//果真如此
//连接Zygote
sZygoteSocket.connect(new LocalSocketAddress(ZYGORE_SOCKET,LocalSocketAddress,Namespace.RESERVED));
sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWrite = new BufferedWriter(new OutputStreamWrite(sZygoteSocket.getOutputStream()),256);
}
}
好了,ActivityManagerService终于向zygote发送请求了。请求的参数中有一个字符串,它的值是“android.app.ActivityThread”。现在该回到zygote处理请求那块中区看看了。
注意:由于ActivityManagerService驻留于SystemServer进程 中所以正是SystemServer向Zygote发送了消息。
4.4.2 有求必应之响应请求
下面我们看看ZygoteInit.java中
【-->ZygoteInit.java】
private static void runSelectLoopMode() throws MethodAndArgsCaller{
......
try{
fdArray = fds.toArray(fdArray);
.....
else if(index == 0){
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
}else{
boolean done;
//调用ZygoteConnection的runOnce。
done = peers.get(index).runOnce();
}
.....
}
}
每当有请求数据发来时,zygote就会调用ZygoteConnection的runOnce函数。
ZygoteConnection代码在ZygoteConnection.java文件中,来看看它的runOnce函数:
【-->ZygoteConnection.java】
boolean runOnce() thows ZygoteInit.MethodAndArgsCaller{
try{
arg = readArgumentList;//读取SystemServer发送过来的参数
descriptors = mSocket.getAncillaryFileDescriptors();
}
.....
int pid;
try{
parseArgs = new Arguments(args);
applyUidSecurityPoilcy(parsenArgs,peer);
//根据函数名,可知Zygote又分裂出了一个子进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,parsedArgs.gids,parsedArgs.debugArgs,parsedArgs.rlimits);
}
......
if(){
//子进程处理,这个子进程是不是我们要创建的Activity对应的子进程?
handleChildProc(parsedArgs,descriptors,newStderr);
return true;
}else{
//zygote进程
return handleParentProc(pid,descriptors,parsedArgs);
}
}
接下来,看看新创建的子进程在handlerChildProc中做了什么。
【-->ZygoteConnection.java】
private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors,PringStream newStderr) throws ZygoteInit.MethodAndArgsCaller{
//根据传入的参数设置新进程的一些属性
//SystemServer发来的参数中有“--runtime-init”,所以parsedArgs.runtimeInit为true。
if(parsedArgs.runtimeInit){
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
}else{
......
}
}
【-->RuntimeInit.java】
public static final void zygoteInit(String[] argv) throws ZyoteInit.MethodAndArgsCaller{
//重定向标准输出和错误输出。
System.setOut(new AndroidPrintStream(Log.INFO,"System.out"));
System.setErr(new AndroidPrintStream(Log.WARN,"System.err"));
commonInit();
//下面这个函数为native函数,最终会调用AppRuntime的onZygoteInit,在那个函数中建立和Buider的关系
zygoteInitNative();
int curArg = 0;
String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];
System.arraycopy(argv,curArg,startArgs,0,startArgs.length);
//最终还是调用invokeStaticMain函数,这个函数我们已经见识过了。
invokeStaticMian(startClass,startArgs);
}
zygote分裂子进程后,自己将handleParentProc中做一些扫尾工作,然后继续等待请求下一次的分裂。
提示:这个android.app.ActivityThread类,实际上是Android中的APK程序所对应的进程,它的main函数就是APK程序的main函数。从这个类的命名(android.app)中也可以看出些端倪。
通过上面的分析,我们可以想到,Android系统运行的那些apk程序,其父都是zygote,可以通过adb shell登陆后,用ps命令查看父进程号来确认。