android源码阅读—–Zygote进程
Zygote进程简介:
zygote进程是安卓中非常重要的一个进程,与init进程 SystemServ进程共同支撑着Android环境。
Zygote进程与一般进程的区别是:
一般进程fork出子进程之后,会继续调用系统的exec,将一个新的可执行文件的内容替换当前的进程的代码段,数据段,堆和栈段,然后zogte只调用的了fork,没有调用exec,这是因为Android中执行的是java代码,java代码所执行的环境要求是一样的,就是虚拟机
这也是Zygote进程初始化时会创建虚拟机,同时把需要的系统类库和资源文件加载到内存,当他fork出子进程的时候 子进程也集成了能正常工作的虚拟机和各种资源文件,然后子进程把apk文件的字节码装载进去运行就行了,app的启动时间会少很多
Zgote |
---|
vm |
resorce |
lib |
… |
————————————————————
Child |
---|
vm |
resorce |
lib |
… |
APK字节码 |
跟继承类似,子进程拥有父进程的资源
Zygote进程的初始化
前篇博客有说到,init进程运行的时候会加载init.rc,根据里面的配置来fork一些进程等,有兴趣的童鞋可以去翻,里面分为两种类型,action 和 service Zygote进程就是以service的方式启动的,在5.0系统中,zygote的启动发生了一些变化,以前是直接写在init.rc的代码块中的,现在则通过import的方式引用过来了
import /init.${ro.zygote}.rc
上面可以看到,init.rc并不是直接引用哪个固定的文件,而是根据ro.zyote的内容来引入不同的文件。这个主要是因为从5.0开始Android开始支持64位的编译(喜大普奔),所以zygote也会有32和64位版本的区别,在init.rc同一目录下,有这么四个文件
init.zygote32_64.rc
init.zygote32.rc
init.zygote64_32.rc
init.zygote64.rc
从这里看出 android支持四种运行模式, 纯32位,纯64位,32为主、64为辅,64为主,32为辅
init.zygote32_64.rc
service zygote /system/bin/app_process32 -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 media
onrestart restart netd
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
上面的代码有过敲命令行的童鞋应该了解怎么回事了,他执行的是app_process32 sencondary执行的是64位的,这就好理解了。
app_process位于frameworks/base/cmds/app_process/app_main.cpp main函数如下,代码有些长,不过自己加了一点关键性的注释,希望能耐着性子看一下
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
int main(int argc, char* const argv[])
{
......
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 "parent dir", which
// 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;
}
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 "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;//"zygote"
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (