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的启动过程。