4.1.2 如何执行zygote服务程序
根据服务程序的路径名在Android.mk文件中定位app_process,其源码位于frameworks/base/cmds/app_process/app_main.cpp。在源码中提供了app_process的启动方式,如下所示:
app_process[java-options]cmd-dir start-class-name[options]
各个参数的作用如下:
[java-options]:可选项,指定传递给虚拟机的参数,以-为前缀。
cmd-dir:必选项,指定要运行的进程。
start-class-name:必选项,指定要加载到虚拟机的类。
[options]:可选项,指定传递给类的参数。
接下来分析app_process的main函数,代码如下:
/*app_main.cpp中给出了启动这个进程的用法:
app_process[java-options]cmd-dir start-class-name[options]/
int main(int argc, const char*const argv[])
{
//ProcessState.cpp中定义的全局变量
mArgC=argc;
mArgV=argv;
mArgLen=0;
for(int i=0;i<argc;i++){
mArgLen+=strlen(argv[i])+1;
}
mArgLen—;
/使用到了类AppRuntime,它是AndroidRuntime的派生类/
AppRuntime runtime;
const char*argv0=argv[0];
argc—;
argv++;//因为argv[0]不是参数,所以首先忽略argv[0],并将argc减1
/处理命令行参数,会把-Xzygote存入AppRuntime的mOption变量中/
int i=runtime.addVmArguments(argc, argv);
bool zygote=false;
bool startSystemServer=false;
bool application=false;
const char*parentDir=NULL;
const char*niceName=NULL;
const char*className=NULL;
while(i<argc){
const char*arg=argv[i++];
if(!parentDir){
parentDir=arg;//将/system/bin存入AppRuntime的mParentDir变量
}else if(strcmp(arg,"—zygote")==0){
/如果参数中指定了—zygote,则启动zygote, nice name设置为zygote/
zygote=true;
bniceName="zygote";
}else if(strcmp(arg,"—start-system-server")==0){
startSystemServer=true;//是否启动System Server
}else if(strcmp(arg,"—application")==0){
application=true;//是否是启动application
}else if(strncmp(arg,"—nice-name=",12)==0){
niceName=arg+12;//是否指定了nice name
}else{
className=arg;
break;
}
}
if(niceName&&*niceName){
setArgv0(argv0,niceName);
/*根据nice name调用系统函数prctl、open、write修改进程名,由于启动过程中
*指定了—zygote参数,所以这里的进程名是zygote。这便是为什么Android.mk文件
中指定进程名为LOCAL_MODULE:=app_process,而实际进程名却是zygote/
set_process_name(niceName);
}
runtime.mParentDir=parentDir;
/if-else用于匹配两种启动类型:启动zygote或者启动Application/
if(zygote){
/如果参数中指定了—zygote,则是启动zygote/
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer?"start-system-server":"");
}else if(className){//这里启动应用程序
runtime.mClassName=className;
runtime.mArgC=argc-i;
runtime.mArgV=argv+i;
runtime.start("com.android.internal.os.RuntimeInit",
application?"application":"tool");
}else{……//省略错误处理代码
}
}
app_main. cpp的main函数非常简单,主要根据传入的4个参数选择相应处理流程,其工作分为三部分:
1)处理参数-Xzygote,设置虚拟机选项。
2)处理参数—zygote,修改进程名为zygote。
3)根据参数—zygote和—start-system-server判断调用AppRuntime的start方法启动ZygoteInit或者RuntimeInit(这里启动的是ZygoteInit)。
可见,app_process最重要的工作交给了AppRuntime类的start方法去完成。在start方法中将执行ZygoteInit类的main方法启动zygote。
注意 这里有一个问题,既然zygote是在init.rc中定义的Daemon Service,为什么不直接通过init启动Service的方式启动zygote呢?
答案是:zygote不同于其他Daemon Service,它是由Java语言编写的,不能由init通过fork子进程的方式启动,因此需要app_process完成加载工作。这也是为什么app_process此时需要修改nice name为zygote的原因。
下一节将详细分析ZygoteInit的启动过程。