Android Zygote系统进程启动过程分析Android N.docx
《Android Zygote系统进程启动过程分析Android N.docx》由会员分享,可在线阅读,更多相关《Android Zygote系统进程启动过程分析Android N.docx(27页珍藏版)》请在冰点文库上搜索。
AndroidZygote系统进程启动过程分析AndroidN
AndroidZygote系统进程启动过程分析(AndroidN)
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,因为Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。
Zygote进程也不例外,它是在系统启动的过程,由init进程创建的,在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
import/init.${ro.zygote}.rc
从上面的代码可以看出,在system/core/rootdir目录下系统不止一个zygote*.rc文件
每个文件里的启动zygote方式差不多,下面就以init.zygote64_32.rc为例看下里面的代码
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
servicezygote/system/bin/app_process64-Xzygote/system/bin--zygote--start-system-server--socket-name=zygote
classmain
socketzygotestream660rootsystem
onrestartwrite/sys/android_power/request_statewake
onrestartwrite/sys/power/stateon
onrestartrestartaudioserver
onrestartrestartcameraserver
onrestartrestartmedia
onrestartrestartnetd
writepid/dev/cpuset/foreground/tasks
servicezygote_secondary/system/bin/app_process32-Xzygote/system/bin--zygote--socket-name=zygote_secondary
classmain
socketzygote_secondarystream660rootsystem
onrestartrestartzygote
writepid/dev/cpuset/foreground/tasks
看到上面的代码估计你也能猜出来另外三个zygote*.rc是怎样的,具体选择哪个文件和编译时定义的ro.zygote值有关。
前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个
zygote进程要执行的程序是/system/bin/app_process64,后面是要传给app_process64的参数。
接下来的"classmain"表示执行system/bin/app_process64后调用main方法,socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以
在/dev/socket目录下看到有一个名为zygote的文件,onrestart关键字表示这个zygote进程重启时需要执行的命令,最后一个writepid关键字表示需要重写系统pid。
通过上面我们知道Zygote进程要执行的程序便是app_process64了,它位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。
(app_process64orapp_process32都是通过
frameworks/base/cmds/app_process编译出来的,只是由编译环境来决定生成那个文件),在分析zygote进程启动之前,来看看它启动的时序图
下面就看看从app_process64到Zygote启动具体流程:
1、在app_main.cpp的main函数中利用AndroidRuntime启动Zygote
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
intmain(intargc,char*constargv[])
{
if(prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0)<0){
//Olderkernelsdon'tunderstandPR_SET_NO_NEW_PRIVSandreturn
//EINVAL.Don'tdieonsuchkernels.
if(errno!
=EINVAL){
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVSfailed:
%s",strerror(errno));
return12;
}
}
AppRuntimeruntime(argv[0],computeArgBlockSize(argc,argv));
//Processcommandlinearguments
//ignoreargv[0]
argc--;
argv++;
//Everythingupto'--'orfirstnon'-'arggoestothevm.
//
//ThefirstargumentaftertheVMargsisthe"parentdir",which
//iscurrentlyunused.
//
//Aftertheparentdir,weexpectoneormorethefollowinginternal
//arguments:
//
//--zygote:
Startinzygotemode
//--start-system-server:
Startthesystemserver.
//--application:
Startinapplication(standalone,nonzygote)mode.
//--nice-name:
Thenicenameforthisprocess.
//
//Fornonzygotestarts,theseargumentswillbefollowedby
//themainclassname.Allremainingargumentsarepassedto
//themainmethodofthisclass.
//
//Forzygotestarts,allremainingargumentsarepassedtothezygote.
//mainfunction.
//
//Notethatwemustcopyargumentstringvaluessincewewillrewritethe
//entireargumentblockwhenweapplythenicenametoargv0.
inti;
for(i=0;iif(argv[i][0]!
='-'){
break;
}
if(argv[i][1]=='-'&&argv[i][2]==0){
++i;//Skip--.
break;
}
runtime.addOption(strdup(argv[i]));
}
//Parseruntimearguments.Stopatfirstunrecognizedoption.
boolzygote=false;
boolstartSystemServer=false;
boolapplication=false;
String8niceName;
String8className;
++i;//Skipunused"parentdir"argument.
while(iconstchar*arg=argv[i++];
if(strcmp(arg,"--zygote")==0){
zygote=true;
niceName=ZYGOTE_NICE_NAME;
}elseif(strcmp(arg,"--start-system-server")==0){
startSystemServer=true;
}elseif(strcmp(arg,"--application")==0){
application=true;
}elseif(strncmp(arg,"--nice-name=",12)==0){
niceName.setTo(arg+12);
}elseif(strncmp(arg,"--",2)!
=0){
className.setTo(arg);
break;
}else{
--i;
break;
}
}
Vectorargs;
if(!
className.isEmpty()){
//We'renotinzygotemode,theonlyargumentweneedtopass
//toRuntimeInitistheapplicationargument.
//
//TheRemainderofargsgetpassedtostartupclassmain().Make
//copiesofthembeforeweoverwritethemwiththeprocessname.
args.add(application?
String8("application"):
String8("tool"));
runtime.setClassNameAndArgs(className,argc-i,argv+i);
}else{
//We'reinzygotemode.
maybeCreateDalvikCache();
if(startSystemServer){
args.add(String8("start-system-server"));
}
charprop[PROP_VALUE_MAX];
if(property_get(ABI_LIST_PROPERTY,prop,NULL)==0){
LOG_ALWAYS_FATAL("app_process:
UnabletodetermineABIlistfromproperty%s.",
ABI_LIST_PROPERTY);
return11;
}
String8abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
//Inzygotemode,passallremainingargumentstothezygote
//main()method.
for(;iargs.add(String8(argv[i]));
}
}
if(!
niceName.isEmpty()){
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if(zygote){
runtime.start("com.android.internal.os.ZygoteInit",args,zygote);//启动ZygoteInit
}elseif(className){
runtime.start("com.android.internal.os.RuntimeInit",args,zygote);
}else{
fprintf(stderr,"Error:
noclassnameor--zygotesupplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process:
noclassnameor--zygotesupplied.");
return10;
}
}
main函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数,AppRuntime这个类同样是在frameworks/base/cmds/app_process/app_main.cpp文件中定义:
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
classAppRuntime:
publicAndroidRuntime
{
public:
AppRuntime(char*argBlockStart,constsize_targBlockLength)
:
AndroidRuntime(argBlockStart,argBlockLength)
mClass(NULL)
{
}
voidsetClassNameAndArgs(constString8&className,intargc,char*const*argv){
mClassName=className;
for(inti=0;imArgs.add(String8(argv[i]));
}
}
virtualvoidonVmCreated(JNIEnv*env)
{
if(mClassName.isEmpty()){
return;//Zygote.Nothingtodohere.
}
char*slashClassName=toSlashClassName(mClassName.string());
mClass=env->FindClass(slashClassName);
if(mClass==NULL){
ALOGE("ERROR:
couldnotfindclass'%s'\n",mClassName.string());
}
free(slashClassName);
mClass=reinterpret_cast(env->NewGlobalRef(mClass));
}
virtualvoidonStarted()
{
spproc=ProcessState:
:
self();
ALOGV("Appprocess:
startingthreadpool.\n");
proc->startThreadPool();
AndroidRuntime*ar=AndroidRuntime:
:
getRuntime();
ar->callMain(mClassName,mClass,mArgs);
IPCThreadState:
:
self()->stopProcess();
}
virtualvoidonZygoteInit()
{
spproc=ProcessState:
:
self();
ALOGV("Appprocess:
startingthreadpool.\n");
proc->startThreadPool();
}
virtualvoidonExit(intcode)
{
if(mClassName.isEmpty()){
//ifzygote
IPCThreadState:
:
self()->stopProcess();
}
AndroidRuntime:
:
onExit(code);
}
String8mClassName;
VectormArgs;
jclassmClass;
};
回到上面的main函数中,由于我们在init.zygote64_32.rc文件中,设置了app_process启动参数--zygote和--start-system-server,因此,在main函数里面,最终会执行下面语句:
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
runtime.start("com.android.internal.os.ZygoteInit",args,zygote);
args参数,在上面main函数里定义的,从main函数可以看出还需要启动start-system-server,这个方法的实现具体如下
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
frameworks/base/core/jni/AndroidRuntime.cpp
voidAndroidRuntime:
:
start(constchar*className,constVector&options,boolzygote)
{
ALOGD(">>>>>>START%suid%d<<<<<<\n",
className!
=NULL?
className:
"(unknown)",getuid());
staticconstString8startSystemServer("start-system-server");
/*
*'startSystemServer==true'meansruntimeisobsoleteandnotrunfrom
*init.rcanymore,soweprintoutthebootstarteventhere.
*/
for(size_ti=0;iif(options[i]==startSystemServer){
/*trackourprogressthroughthebootsequence*/
constintLOG_BOOT_PROGRESS_START=3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
constchar*rootDir=getenv("ANDROID_ROOT");
if(rootDir==NULL){
rootDir="/system";
if(!
hasDir("/system")){
LOG_FATAL("Norootdirectoryspecified,and/androiddoesnotexist.");
return;
}
setenv("ANDROID_ROOT",rootDir,1);
}
//constchar*kernelHack=getenv("LD_ASSUME_KERNEL");
//ALOGD("FoundLD_ASSUME_KERNEL='%s'\n",kernelHack);
/*startthevirtualmachine*/
JniInvocationjni_invocation;
jni_invocation.Init(NULL);
JNIEnv*env;
if(startVm(&mJavaVM,&env,zygote)!
=0){
return;
}
onVmCreated(env);
/*
*Registerandroidfunctions.
*/
if(startReg(env)<0){
ALOGE("Unabletoregisterallandroidnatives\n");
return;
}
/*
*Wewanttocallmain()withaStringarraywithargumentsinit.
*Atpresentwehavetwoarguments,theclassnameandanoptionstring.
*Createanarraytoholdthem.
*/
jclassstringClass;
jobjectArraystrArray;
jstringclassNameStr;
stringClass=env->FindClass("java/lang/String");
assert(stringClass!
=NULL);
strArray=env->NewObjectArray(options.size()+1,stringClass,NULL);
assert(strArray!
=NULL);
classNameStr=env->NewStringUTF(className);
assert(classNameStr!
=