Android系统进程Zygote启动过程的源代码分析
声明:
RTFSC(Read the fucking source code)是Linus的名言,也是学习IT技术一个重要手段。学习android最好手段就是对android进行系统分析,关于android系统的源码,CSDN的老罗分析分析是最系统一个。但是老罗的分析源码的blog,有几点不够好:
1.废话太多,可能考虑太多的小白读者,可以谅解。
2.分析结果一般都一文字形式存在于博文内部,对于一些急需结论的用户,笔者将分析后结果提前了。
3.老罗blog有些讲的不全的地方,笔者有补充,但建议读老罗的blog, 原汁原味。
4.本blog更多以监督自己学习为主,需要看官监督下,才能有心继续。
5.每篇文章都标明文章出处,尊重老罗的辛勤输出,我只是一个二次传播者
在android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。Zygote进程的启动是又是由android的系统进程init解析init.rc文件来启动的。系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
3.onrestart关键字: 表示这个zygote进程重启时需要执行的命令。
关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。
分析结论:
1. init进程通过解析init.rc启动Zygote进程, Zygote进程会完成以工作
2. 启动虚拟机(ART或者Dalivk)
3. 创建一个名ANDROID_SOCKET_zygote机的服务Socket. 这个socket用于AMS的请求Zygote 创建一个Android应用程序的进程。
4. 启动SystemServer进程,SystemServer进程回启动android系统中各种服务,其中比较重要的AMS, PMS。 在SystemServer中会关闭Socket, 因为android系统的组件和SystemServer不在使用Socket机制,而是使用Binder机制。
5. Zygote进程进入循环等待Socket连接状态。 一旦AMS有请求Zygote进程请求创建一个android 应用程序进程, 就会调用ZygoteConnection.runOnce。
分析过程:
Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。在分析Zygote进程启动的过程之前,我们先来看看它的启动序列图,从总体流程看看Zygote启动进程简单过程。
下面我们就详细分析每一个步骤。
Step 1. app_process.main 这个函数定义在frameworks/base/cmds/app_process/app_main.cpp
int main(int argc,constchar*const argv[])
{
// These are global variables in ProcessState.cpp
AppRuntime runtime;
.....
// Next arg is parent directory
if(i < argc){
runtime.mParentDir = argv[i++];
}
// Next arg is startup classname or "--zygote"
if(i < argc){
arg = argv[i++];
if(0== strcmp("--zygote", arg)){
bool startSystemServer =(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{
......
}
}
}
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
Step 2. AndroidRuntime.start : frameworks/base/core/jni/AndroidRuntime.cpp plain
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
voidAndroidRuntime::start(constchar* className,constchar* options)
{
- ....
/* start the virtual machine */
JNIEnv* env;
if(startVm(&mJavaVM,&env)!=0){
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if(startReg(env)<0){
LOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray,0, classNameStr);
optionsStr = env->NewStringUTF(options);
env->SetObjectArrayElement(strArray,1, optionsStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if(startClass == NULL){
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
}else{
jmethodID startMeth = env->GetStaticMethodID(startClass,"main",
"([Ljava/lang/String;)V");
if(startMeth == NULL){
LOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
}else{
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
free(slashClassName);
}
这个函数的作用是启动Android系统运行时库,它主要做了三件事情,
1.一是调用函数startVM启动虚拟机(这个会在稍后虚拟机源码分析源码系列讲解)
2.二是调用函数startReg注册JNI方法 (建立android系统,Java层-Native层之间的联系)
3.三是调用了com.android.internal.os.ZygoteInit类的main函数。
Step 3. ZygoteInit.main : frameworks/base/core/Java/com/android/internal/os/ZygoteInit.java
publicclassZygoteInit{
......
publicstaticvoid main(String argv[]){
try{
......
registerZygoteSocket();
......
......
if(argv[1].equals("true")){
startSystemServer();
}elseif(!argv[1].equals("false")){
......
}
......
if(ZYGOTE_FORK_MODE){
......
}else{
runSelectLoopMode();
}
......
}catch(MethodAndArgsCaller caller){
......
}catch(RuntimeException ex){
......
}
}
......
}
view plai copy
publicclassZygoteInit{
......
privatestaticfinalString ANDROID_SOCKET_ENV ="ANDROID_SOCKET_zygote";
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
privatestaticvoid registerZygoteSocket(){
if(sServerSocket ==null){
int fileDesc;
try{
String env =System.getenv(ANDROID_SOCKET_ENV);
fileDesc =Integer.parseInt(env);
}catch(RuntimeException ex){
......
}
try{
sServerSocket =newLocalServerSocket(
createFileDescriptor(fileDesc));
}catch(IOException ex){
.......
}
}
}
......
}
view plain co
view pStep 5. ZygoteInit.startSystemServer:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
publicclassZygoteInit{
......
privatestaticboolean startSystemServer()
throwsMethodAndArgsCaller,RuntimeException{
/* Hardcoded command line to start the system server */
String args[]={
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs =null;
int pid;
try{
parsedArgs =newZygoteConnection.Arguments(args);
......
/* Request to fork the system server process */
pid =Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags,null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
}catch(IllegalArgumentException ex){
......
}
/* For child process */
if(pid ==0){
handleSystemServerProcess(parsedArgs);
}
returntrue;
}
......
}
view plain cop
这里我们可以看到,Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer系统进程,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。
Step 6. ZygoteInit.handleSystemServerProcess 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
publicclassZygoteInit{
......
privatestaticvoid handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throwsZygoteInit.MethodAndArgsCaller{
closeServerSocket();
/*
* Pass the remaining arguments to SystemServer.
* "--nice-name=system_server com.android.server.SystemServer"
*/
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
/* should never reach here */
}
......
}
view plain cop
Step 7. RuntimeInit.zygoteInit 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
publicclassRuntimeInit{
......
publicstaticfinalvoid zygoteInit(String[] argv)
throwsZygoteInit.MethodAndArgsCaller{
......
zygoteInitNative();
......
// Remaining arguments are passed to the start class's static main
String startClass = argv[curArg++];
String[] startArgs =newString[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs,0, startArgs.length);
invokeStaticMain(startClass, startArgs);
}
......
}
Step 8. RuntimeInit.zygoteInitNative 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中,这里我们就不再细看了,具体可以参考Android应用程序进程启动过程的源代码分析一文的Step 9,完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。回到Step 7中的RuntimeInit.zygoteInitNative函数,下一步它就要执行com.android.server.SystemServer类的main函数了。
Step 9. SystemServer.main : frameworks/base/services/java/com/android/server/SystemServer.java
publicclassSystemServer
{
......
nativepublicstaticvoid init1(String[] args);
......
publicstaticvoid main(String[] args){
......
init1(args);
......
}
publicstaticfinalvoid init2(){
Slog.i(TAG,"Entered the Android system server!");
Thread thr =newServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
......
}
view plain cop
这里的main函数首先会执行JNI方法init1,然后init1会调用这里的init2函数,在init2函数里面,会创建一个ServerThread线程对象来执行一些系统关键服务的启动操作,例如PMS和AMS。这一步的具体执行过程可以参考Android应用程序安装过程源代码分析一文,这里就不再详述了。
Step 10. ZygoteInit.runSelectLoopMode : frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
publicclassZygoteInit{
......
privatestaticvoid runSelectLoopMode()throwsMethodAndArgsCaller{
ArrayList<FileDescriptor> fds =newArrayList();
ArrayList<ZygoteConnection> peers =newArrayList();
FileDescriptor[] fdArray =newFileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while(true){
int index;
......
try{
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
}catch(IOException ex){
thrownewRuntimeException("Error in select()", ex);
}
if(index <0){
thrownewRuntimeException("Error in select()");
}elseif(index ==0){
ZygoteConnection newPeer =
();peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
}else{
boolean done;
done = peers.get(index).runOnce();
if(done){
peers.remove(index);
fds.remove(index);
}
}
}
}
......
}
view plai co