发布时间 : 星期六 文章Android Zygote系统进程启动过程分析(Android N)更新完毕开始阅读
Android Zygote系统进程启动过程分析
(Android N)
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,因为Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的,在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 import /init.${ro.zygote}.rc
从上面的代码可以看出,在system/core/rootdir目录下系统不止一个zygote*.rc文件
每个文件里的启动zygote方式差不多,下面就以init.zygote64_32.rc为例看下里面的代码
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary class main
socket zygote_secondary stream 660 root system onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
看到上面的代码估计你也能猜出来另外三个zygote*.rc是怎样的,具体选择哪个文件和编译时定义的ro.zygote值有关。前面的关键字service告诉init进程创建一个名为\的进程,这个
zygote进程要执行的程序是/system/bin/app_process64,后面是要传给app_process64的参数。
接下来的\main\表示执行system/bin/app_process64后调用main方法,socket关键字表示这个zygote进程需要一个名称为\的socket资源,这样,系统启动后,我们就可以
在/dev/socket目录下看到有一个名为zygote的文件,onrestart关键字表示这个zygote进程重启时需要执行的命令,最后一个writepid关键字表示需要重写系统pid。
通过上面我们知道Zygote进程要执行的程序便是app_process64了,它位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。(app_process64 or app_process32 都是通过
frameworks/base/cmds/app_process编译出来的,只是由编译环境来决定生成那个文件),在分析zygote进程启动之前,来看看它启动的时序图
下面就看看从app_process64到Zygote启动具体流程:
1、在app_main.cpp的main函数中利用AndroidRuntime启动Zygote
[java] view plain copy 在CODE上查看代码片派生到我的代码片 int main(int argc, char* const argv[]) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return // EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL(\failed: strerror(errno));
return 12; } }
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++;
// Everything up to '--' or first non '-' arg goes to the vm. //
// The first argument after the VM args is the \ // is currently unused. //
// After the parent dir, we expect one or more the following internal // arguments : //
// --zygote : Start in zygote mode
// --start-system-server : Start the system server.
// --application : Start in application (stand alone, non zygote) mode. // --nice-name : The nice name for this process. //
// For non zygote starts, these arguments will be followed by // the main class name. All remaining arguments are passed to // the main method of this class. //
// For zygote starts, all remaining arguments are passed to the zygote. // main function. //
// Note that we must copy argument string values since we will rewrite the // entire argument block when we apply the nice name to argv0.
int i;
for (i = 0; i < argc; i++) { if (argv[i][0] != '-') { break; }
if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --. break;
%s\
}
runtime.addOption(strdup(argv[i])); }
// Parse runtime arguments. Stop at first unrecognized option. bool zygote = false;
bool startSystemServer = false; bool application = false; String8 niceName; String8 className;
++i; // Skip unused \ while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, \ zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, \ startSystemServer = true;
} else if (strcmp(arg, \ application = true;
} else if (strncmp(arg, \ niceName.setTo(arg + 12);
} else if (strncmp(arg, \ className.setTo(arg); break; } else { --i; break; } }
Vector
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass // to RuntimeInit is the application argument. //
// The Remainder of args get passed to startup class main(). Make // copies of them before we overwrite them with the process name. args.add(application ? String8(\ runtime.setClassNameAndArgs(className, argc - i, argv + i); } else {
// We're in zygote mode. maybeCreateDalvikCache();