Android zygote的分裂总结

来源:互联网 发布:nba2k17捏脸数据大全 编辑:程序博客网 时间:2024/04/29 22:16

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命令查看父进程号来确认。