Zygote工作流程分析
Zygote
接收客户端创建进程的请求,使用JNI调用linux fork函数创建进程。
Zygote是在Init进程中作为Service被启动的。Zygote进程的主体是:ZygoteInit。
Zygote进程的启动可以参考前篇:Android系统启动过程
http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html
系统启动过程如下图:
下面主要看看Zygote是如何进行工作的。
一 Zygote工作流程
主函数:
public static void main(String argv[]) {
……
// Registers a server socket for zygote command connections
registerZygoteSocket();
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*/
runSelectLoopMode(); //loop中
}
消息循环是runSelectLoopMode:
private static void runSelectLoopMode() throws MethodAndArgsCaller {
… …
while (true) {
int index;
//异步方式 获取ZygoteConnection Command
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
if(index == 0) {
//读取新的ZygoteConnection Socket
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//处理ZygoteConnection Command
boolean done;
done = peers.get(index).runOnce();
}
}
}
过程如下图所示:
1 ZygoteConnection Command 接收
在ZygoteInit的 main函数中
public static void main(String argv[]) {
……
// Registers a server socket for zygote command connections
registerZygoteSocket();
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*/
runSelectLoopMode(); //loop中
}
//registerZygoteSocket注册了Server 端Socket监听ZygoteConnection:
private static void registerZygoteSocket() {
//” ANDROID_SOCKET_zygote”
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
//private static LocalServerSocket sServerSocket;
if (sServerSocket == null) {
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
}
}
使用到了LocalServerSocket进行通信,具体如何进行请看源码。
2 ZygoteConnection Command处理
在循环中done = peers.get(index).runOnce();——> ZygoteConnection runOnce
boolean runOnce( ) {
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
//Reads one start command from the command socket.
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
//创建/Forks a new VM instance /process.
//使用Jni 调用nativeFork
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
//返回两次
if (pid == 0) {
// in child
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
return true;
} else {
// in parent...pid of < 0 means failure
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
}
3 Zygote创建新进程的执行
从上面的代码中可以看到创建进程之后返回:
子进程:handleChildProc
父进程:handleParentProc
我们关心的是子进程的执行,继续到handleChildProc中。
// Handles post-fork setup of child proc
private void handleChildProc(Arguments parsedArgs,...){
……
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
//通过系统调用执行进程
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
//通过寻找到相应目标类的main()函数并执行
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs);
}
}
……
}
看到子进程的执行有两种方式:
WrapperInit.execApplication和RuntimeInit.zygoteInit:
1)通过系统调用的方式执行进程 WrapperInit.execApplication:
public static void execApplication(……) {
……
Zygote.execShell(command.toString());
}
public static void execShell(String command) {
// using the exec() system call
nativeExecShell(command);
}
2)通过寻找到相应目标类的main()函数并执行 RuntimeInit.zygoteInit:
// The main function called when started through the zygote process.
public static final void zygoteInit( ){
zygoteInitNative();
applicationInit(targetSdkVersion, argv);
}
private static void applicationInit( ) {
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
通过RuntimeInit调用startClass的main函数。
为何两种方式?可以参考下面文章:
http://blog.csdn.net/21cnbao/article/details/7791254
以上是Zygote大概简要的工作流程,要深入了解进程创建过程还不行,以上两种方式执行新创建的进程有何区别,
还得熟悉Android,Linux 及其Fork的一些知识和原理。
linux fork可以参考我转载的文章:
http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html
了解了Zygote大概工作流程,如果我们要创建进程该如何告知Zygote呢?
在StartActivity如果是启动新的应用就会创建该应用的进程,下面我们可以看一下StartActivity时创建进程的过程。
二 应用程序进程的创建过程
启动一个新的应用程序为例,启动新的应用程序时候是以startActivity的方式进行,这个过程大致如下图:
在启动应用程序的时需要创建应用程序的进程,执行到:
ActivityManagerService的startProcessLocked函数中;看一下这个函数过程:
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr)
{
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult =
Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags,
app.info.targetSdkVersion, zygoteArgs);
}
到了Process这个类:Tools for managing OS processes.
public static final ProcessStartResult start(…… ) {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, targetSdkVersion, zygoteArgs);
}
//Starts a new process via the zygote mechanism.
private static ProcessStartResult startViaZygote(…… )
{
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
//参数设置
// --runtime-init, --setuid=, --setgid=,……
//--runtime-init这里决定上面所提到创建新的进程的启动方式
argsForZygote.add("--runtime-init");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
//……
argsForZygote.add(processClass);
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
return zygoteSendArgsAndGetResult(argsForZygote);
}
}
//Sends an argument list to the zygote process, which starts a new child
//and returns the child's pid
private static ProcessStartResult zygoteSendArgsAndGetResult
(ArrayList<String> args)
{
//open socket to Zygote process if not already open
openZygoteSocketIfNeeded();
//write Argument
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.newLine();
sZygoteWriter.flush();
……
}
通过上面这一段代码,向Zygote发送创建进程的请求,设置相关的参数。
其中有argsForZygote.add("--runtime-init"); 决定新创建进程的启动方式为RuntimeInit.zygoteInit方式启动:
找到目标类main函数执行。
processClass为"android.app.ActivityThread",将是进程创建之后执行的类,执行其中的main函数。
联系上面的流程:
即创建进程后执行到RuntimeInit.zygoteInit中:(直接找到目标类的main函数调用不是系统调用)
// The main function called when started through the zygote process.
public static final void zygoteInit( ){
applicationInit(targetSdkVersion, argv);
}
private static void applicationInit( ) {
//后将执行:ActivityThread的main函数,启动界面。
invokeStaticMain(args.startClass, args.startArgs);
}
ActivityThread就是应用程序的主线程的入口。
以上便是Zygote工作流程和启动应用程序创建进程大概简单过程,其中所涉及到知识和框架比较多,还需要去理解linux fork知识和原理,
进程概念,Android进程通信机制Binder,Activity启动过程等。这里仅简单的从代码上做流程分析。
参考文档: