Android系统进程Zygote启动过程的源代码分析(1)
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。由于Zygote进程在Android系统中有着如此重要的地位,本文将详细分析它的启动过程。
在前面一篇文章Android应用程序进程启动过程的源代码分析中,我们看到了,当ActivityManagerService启动一个应用程序的时候,就会通过Socket与Zygote进程进行通信,请求它fork一个子进程出来作为这个即将要启动的应用程序的进程;在前面两篇文章Android应用程序安装过程源代码分析和Android系统默认Home应用程序(Launcher)的启动过程源代码分析中,我们又看到了,系统中的两个重要服务PackageManagerService和ActivityManagerService,都是由SystemServer进程来负责启动的,而SystemServer进程本身是Zygote进程在启动的过程中fork出来的。
我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
[plain] view plain copy- servicezygote/system/bin/app_process-Xzygote/system/bin--zygote--start-system-server
- socketzygotestream666
- onrestartwrite/sys/android_power/request_statewake
- onrestartwrite/sys/power/stateon
- onrestartrestartmedia
- onrestartrestartnetd
前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。
接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具体可以参考前面一篇文章Android学习启动篇提到的一书《Linux内核源代码情景分析》的第七章--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。
最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。
关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。
了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。在继续分析Zygote进程启动的过程之前,我们先来看看它的启动序列图:
下面我们就详细分析每一个步骤。
Step 1. app_process.main
这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:
[cpp] view plain copy- intmain(intargc,constchar*constargv[])
- {
- //TheseareglobalvariablesinProcessState.cpp
- mArgC=argc;
- mArgV=argv;
- mArgLen=0;
- for(inti=0;i<argc;i++){
- mArgLen+=strlen(argv[i])+1;
- }
- mArgLen--;
- AppRuntimeruntime;
- constchar*arg;
- argv0=argv[0];
- //Processcommandlinearguments
- //ignoreargv[0]
- argc--;
- argv++;
- //Everythingupto'--'orfirstnon'-'arggoestothevm
- inti=runtime.addVmArguments(argc,argv);
- //Nextargisparentdirectory
- if(i<argc){
- runtime.mParentDir=argv[i++];
- }
- //Nextargisstartupclassnameor"--zygote"
- if(i<argc){
- arg=argv[i++];
- if(0==strcmp("--zygote",arg)){
- boolstartSystemServer=(i<argc)?
- strcmp(argv[i],"--start-system-server")==0:false;
- setArgv0(argv0,"zygote");
- set_process_name("zygote");
- runtime.start("com.android.internal.os.ZygoteInit",
- startSystemServer);
- }else{
- set_process_name(argv0);
- runtime.mClassName=arg;
- //Remainderofargsgetpassedtostartupclassmain()
- runtime.mArgC=argc-i;
- runtime.mArgV=argv+i;
- LOGV("Appprocessisstartingwithpid=%d,class=%s.\n",
- getpid(),runtime.getClassName());
- runtime.start();
- }
- }else{
- LOG_ALWAYS_FATAL("app_process:noclassnameor--zygotesupplied.");
- fprintf(stderr,"Error:noclassnameor--zygotesupplied.\n");
- app_usage();
- return10;
- }
- }
这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。AppRuntime这个类我们在Android应用程序进程启动过程的源代码分析一文中已经有过介绍了,它同样是在frameworks/base/cmds/app_process/app_main.cpp文件中定义:[cpp]view plaincopy
- classAppRuntime:publicAndroidRuntime
- {
- ......
- };
它约继承于AndroidRuntime类,AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
[cpp] view plain copy- ......
- staticAndroidRuntime*gCurRuntime=NULL;
- ......
- AndroidRuntime::AndroidRuntime()
- {
- ......
- assert(gCurRuntime==NULL);//oneperprocess
- gCurRuntime=this;
- }
当AppRuntime对象创建时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将this指针保存在静态全局变量gCurRuntime中,这样,当其它地方需要使用这个AppRuntime对象时,就可以通过同一个文件中的这个函数来获取这个对象的指针:
[cpp] view plain copy- AndroidRuntime*AndroidRuntime::getRuntime()
- {
- returngCurRuntime;
- }
回到上面的main函数中,由于我们在init.rc文件中,设置了app_process启动参数--zygote和--start-system-server,因此,在main函数里面,最终会执行下面语句:
[cpp] view plain copy- runtime.start("com.android.internal.os.ZygoteInit",
- rtSystemServer);
这里的参数startSystemServer为true,表示要启动SystemServer组件。由于AppRuntime没有实现自己的start函数,它继承了父类AndroidRuntime的start函数,因此,下面会执行AndroidRuntime类的start函数。
更多相关文章
- C语言函数的递归(上)
- Android(安卓)studio使用NDK编译和调试(生成so文件)
- Android(安卓)混淆打包
- Service与Android系统设计(2)
- ORB_SLAM2在android studio上用cmake编译
- 带你一步一步手动实现Android热更新
- Eclipse下载Github用Android(安卓)Studio编辑的Android源码
- Android的APK反编译技术
- 为什么 Android(安卓)手机总是越用越慢