android启动过程分析--启动zygote

转载:https://i-blog.csdnimg.cn/blog_migrate/875a884c5a4d7545f564107f5283b1f1.png


zygote的启动是通过init.rc,我们看下init.rc中有如下几行:

  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  
  2.     socket zygote stream 666  
  3.     #onrestart write /sys/android_power/request_state wake  
  4.     #onrestart write /sys/power/state on  
  5.     onrestart restart media  
  6.     onrestart restart netd  

所以 zygote是init进程的子进程。

在Android系统中,所 有的应用程序以及系统服务SystemServer都是由Zygote fork出来的,这或许就是为什么它叫zygote(受精卵)的原因把。

在解析init.rc 的时候会把zygote加到service列表中,并最终调用do_service启动,从上面可以看到zygote启动的实际是app_process程序,我们看下zygote的启动流程:


1、main函数

  1. if (0 == strcmp("--zygote", arg)) {  
  2.             bool startSystemServer = (i < argc) ?   
  3.                     strcmp(argv[i], "--start-system-server") == 0 : false;  
  4.             setArgv0(argv0, "zygote");  
  5.             set_process_name("zygote");  
  6.             runtime.start("com.android.internal.os.ZygoteInit",  
  7.                 startSystemServer);  

代码路径在: Frameworks/base/cmds/app_process的app_main.cpp中,我们看下main函数中有如下几行:

  1. if (0 == strcmp("--zygote", arg)) {  
  2.             bool startSystemServer = (i < argc) ?   
  3.                     strcmp(argv[i], "--start-system-server") == 0 : false;  
  4.             setArgv0(argv0, "zygote");  
  5.             set_process_name("zygote");  
  6.             runtime.start("com.android.internal.os.ZygoteInit",  
  7.                 startSystemServer);  
从上面的脚本可以看出传进来的参数是-Xzygote /system/bin --zygote --start-system-server,所以这里会走到这个if分支,这里设置了进程的名字为"zygote",然后调用runttime.start启动zygote.

2、runtime.start()

  1. void AndroidRuntime::start(const char* className, const bool startSystemServer)  
  2. {  
  3.     LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",  
  4.             className != NULL ? className : "(unknown)");  
  5.    .  
  6.    .  
  7.    /* start the virtual machine */  
  8.     if (startVm(&mJavaVM, &env) != 0)  
  9.         goto bail;  
  10.   
  11.     /* 
  12.      * Register android functions. 
  13.      */  
  14.     if (startReg(env) < 0) {  
  15.         LOGE("Unable to register all android natives\n");  
  16.         goto bail;  
  17.     }  
  18.     .  
  19.     .  
  20.     startClass = env->FindClass(slashClassName);  
  21.     if (startClass == NULL) {  
  22.         LOGE("JavaVM unable to locate class '%s'\n", slashClassName);  
  23.         /* keep going */  
  24.     } else {  
  25.         startMeth = env->GetStaticMethodID(startClass, "main",  
  26.             "([Ljava/lang/String;)V");  
  27.         if (startMeth == NULL) {  
  28.             LOGE("JavaVM unable to find main() in '%s'\n", className);  
  29.             /* keep going */  
  30.         } else {  
  31.             env->CallStaticVoidMethod(startClass, startMeth, strArray);  
  32.     }  
  33. }  
在这里启动虚拟机,注册jni函数,最后找到com.android.internal.os.ZygoteInit类并调用他的main函数跳转到java环境中。

3、zygoteInit.main

  1. public static void main(String argv[]) {  
  2.     try {  
  3.         VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);  
  4.   
  5.         // Start profiling the zygote initialization.  
  6.         SamplingProfilerIntegration.start();  
  7.   
  8.         registerZygoteSocket();  
  9.         EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,  
  10.             SystemClock.uptimeMillis());  
  11.         preloadClasses();  
  12.         //cacheRegisterMaps();  
  13.         preloadResources();  
  14.         EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,  
  15.             SystemClock.uptimeMillis());  
  16.   
  17.         // Finish profiling the zygote initialization.  
  18.         SamplingProfilerIntegration.writeZygoteSnapshot();  
  19.   
  20.         // Do an initial gc to clean up after startup  
  21.         gc();  
  22.   
  23.         // If requested, start system server directly from Zygote  
  24.         if (argv.length != 2) {  
  25.             throw new RuntimeException(argv[0] + USAGE_STRING);  
  26.         }  
  27.   
  28.         if (argv[1].equals("true")) {  
  29.             startSystemServer();  
  30.         } else if (!argv[1].equals("false")) {  
  31.             throw new RuntimeException(argv[0] + USAGE_STRING);  
  32.         }  
  33.   
  34.         Log.i(TAG, "Accepting command socket connections");  
  35.   
  36.         if (ZYGOTE_FORK_MODE) {  
  37.             runForkMode();  
  38.         } else {  
  39.             runSelectLoopMode();  
  40.         }  
  41.   
  42.         closeServerSocket();  
  43.     } catch (MethodAndArgsCaller caller) {  
  44.         caller.run();  
  45.     } catch (RuntimeException ex) {  
  46.         Log.e(TAG, "Zygote died with exception", ex);  
  47.         closeServerSocket();  
  48.         throw ex;  
  49.     }  
  50. }  

在这里调用registerZygoteSocket建立了一个socket监听,用来和 ActivityManagerService进行通迅。注意这里利用System.getenv()获取"ANDROID_SOCKET_zygote这个环境变量对应的描述符,和我们前面 android usb挂载分析----vold启动文章中讲的获取"vold‘套接字是一样的,不过是这里传入的是整个环境变量的名称,而前面vold启动中传的是“vold"字符串,再在后面调用了android_get_control_socket在里面加上前缀组合成环境变量名再去获取的。
  1. private static void registerZygoteSocket() {  
  2.     if (sServerSocket == null) {  
  3.         int fileDesc;  
  4.         try {  
  5.             String env = System.getenv(ANDROID_SOCKET_ENV);  
  6.             fileDesc = Integer.parseInt(env);  
  7.         } catch (RuntimeException ex) {  
  8.             throw new RuntimeException(  
  9.                     ANDROID_SOCKET_ENV + " unset or invalid", ex);  
  10.         }  
  11.   
  12.         try {  
  13.             sServerSocket = new LocalServerSocket(  
  14.                     createFileDescriptor(fileDesc));  
  15.         } catch (IOException ex) {  
  16.             throw new RuntimeException(  
  17.                     "Error binding to local socket '" + fileDesc + "'", ex);  
  18.         }  
  19.     }  
  20. }  

LocalServerSocket即进行了监听操作:
  1. public LocalServerSocket(FileDescriptor fd) throws IOException  
  2. {  
  3.     impl = new LocalSocketImpl(fd);  
  4.     impl.listen(LISTEN_BACKLOG);  
  5.     localAddress = impl.getSockAddress();  
  6. }  
接下来预加载一些类和资源
  1. preloadClasses();  
  2. //cacheRegisterMaps();  
  3. preloadResources();  

启动系统服务
  1. if (argv[1].equals("true")) {  
  2.      startSystemServer();  
  3.  }  
看下startSystemServer()
  1. /** 
  2.  * Prepare the arguments and fork for the system server process. 
  3.  */  
  4. private static boolean startSystemServer()  
  5.         throws MethodAndArgsCaller, RuntimeException {  
  6.     /* Hardcoded command line to start the system server */  
  7.     String args[] = {  
  8.         "--setuid=1000",  
  9.         "--setgid=1000",  
  10.         "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",  
  11.         "--capabilities=130104352,130104352",  
  12.         "--runtime-init",  
  13.         "--nice-name=system_server",  
  14.         "com.android.server.SystemServer",  
  15.     };  
  16.     ZygoteConnection.Arguments parsedArgs = null;  
  17.   
  18.     int pid;  
  19.   
  20.     try {  
  21.         parsedArgs = new ZygoteConnection.Arguments(args);  
  22.   
  23.         /* 
  24.          * Enable debugging of the system process if *either* the command line flags 
  25.          * indicate it should be debuggable or the ro.debuggable system property 
  26.          * is set to "1" 
  27.          */  
  28.         int debugFlags = parsedArgs.debugFlags;  
  29.         if ("1".equals(SystemProperties.get("ro.debuggable")))  
  30.             debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;  
  31.   
  32.         /* Request to fork the system server process */  
  33.         pid = Zygote.forkSystemServer(  
  34.                 parsedArgs.uid, parsedArgs.gid,  
  35.                 parsedArgs.gids, debugFlags, null,  
  36.                 parsedArgs.permittedCapabilities,  
  37.                 parsedArgs.effectiveCapabilities);  
  38.     } catch (IllegalArgumentException ex) {  
  39.         throw new RuntimeException(ex);  
  40.     }  
  41.   
  42.     /* For child process */  
  43.     if (pid == 0) {  
  44.         handleSystemServerProcess(parsedArgs);  
  45.     }  
  46.   
  47.     return true;  
  48. }  

这里调用forkSystemServer fork一个子进程,父进程直接返回,子进程执行handleSystemServerProcess
Zygote.forkSystemServer最终调用Dalvik_dalvik_system_Zygote_forkSystemServer
  1. static void Dalvik_dalvik_system_Zygote_forkSystemServer(  
  2.         const u4* args, JValue* pResult)  
  3. {  
  4.     pid_t pid;  
  5.     pid = forkAndSpecializeCommon(args, true);  
  6.   
  7.     /* The zygote process checks whether the child process has died or not. */  
  8.     if (pid > 0) {  
  9.         int status;  
  10.   
  11.         LOGI("System server process %d has been created", pid);  
  12.         gDvm.systemServerPid = pid;  
  13.         /* There is a slight window that the system server process has crashed 
  14.          * but it went unnoticed because we haven't published its pid yet. So 
  15.          * we recheck here just to make sure that all is well. 
  16.          */  
  17.         if (waitpid(pid, &status, WNOHANG) == pid) {  
  18.             LOGE("System server process %d has died. Restarting Zygote!", pid);  
  19.             kill(getpid(), SIGKILL);  
  20.         }  
  21.     }  
  22.     RETURN_INT(pid);  
  23. }  
这里,在父进程里调用waitpid,这里的pid是子进程也即systemServer的pid,也就是说当systemServer退出的时候杀死父进程(zygote)
  1. static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)  
  2. {  
  3.    ...  
  4.    setSignalHandler();  
  5. }  
在这里,父子进程者注册了一个子进程退出的信号
  1. static void setSignalHandler()  
  2. {  
  3.     int err;  
  4.     struct sigaction sa;  
  5.   
  6.     memset(&sa, 0, sizeof(sa));  
  7.   
  8.     sa.sa_handler = sigchldHandler;  
  9.   
  10.     err = sigaction (SIGCHLD, &sa, NULL);  
  11.   
  12.     if (err < 0) {  
  13.         LOGW("Error setting SIGCHLD handler: %s", strerror(errno));  
  14.     }  
  15. }  

这里在注册了一个子进程退出的信号,处理函数:
  1. <span style="color:#333333;">static void sigchldHandler(int s)  
  2. {  
  3.     pid_t pid;  
  4.     int status;  
  5.   
  6.     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {  
  7.         if (WIFEXITED(status)) {  
  8.             if (WEXITSTATUS(status)) {  
  9.                 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)\n",  
  10.                     (int) pid, WEXITSTATUS(status));  
  11.             } else {  
  12.                 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {  
  13.                     LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,  
  14.                         "Process %d exited cleanly (%d)\n",  
  15.                         (int) pid, WEXITSTATUS(status));  
  16.                 }  
  17.             }  
  18.         } else if (WIFSIGNALED(status)) {  
  19.             if (WTERMSIG(status) != SIGKILL) {  
  20.                 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG,  
  21.                     "Process %d terminated by signal (%d)\n",  
  22.                     (int) pid, WTERMSIG(status));  
  23.             } else {  
  24.                 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {  
  25.                     LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,  
  26.                         "Process %d terminated by signal (%d)\n",  
  27.                         (int) pid, WTERMSIG(status));  
  28.                 }  
  29.             }  
  30. #ifdef WCOREDUMP  
  31.             if (WCOREDUMP(status)) {  
  32.                 LOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core\n",  
  33.                     (int) pid);  
  34.             }  
  35. #endif /* ifdef WCOREDUMP */  
  36.         }  
  37.   
  38.         /* 
  39.          * If the just-crashed process is the system_server, bring down zygote 
  40.          * so that it is restarted by init and system server will be restarted 
  41.          * from there. 
  42.          */  
  43.         if (pid == gDvm.systemServerPid) {  
  44.             LOG(LOG_INFO, ZYGOTE_LOG_TAG,  
  45.               “Exit zygote because system server (%d) has terminated\n”);  
  46.             kill(getpid(), SIGKILL);  
  47.         }  
  48.     }  
  49.   
  50.     if (pid < 0) {  
  51.         LOG(LOG_WARN, ZYGOTE_LOG_TAG,  
  52.             "Zygote SIGCHLD error in waitpid: %s\n",strerror(errno));  
  53.     }  
  54. }  
  55. </span>  



继续跟踪main函数,父进程返回后
  1. if (ZYGOTE_FORK_MODE) {  
  2.                 runForkMode();  
  3.             } else {  
  4.                 runSelectLoopMode();  
  5.             }  

这进而ZYGOTE_FORK_MODE为false所以执行runSelectLoopMode
  1. /** 
  2.  * Runs the zygote process's select loop. Accepts new connections as 
  3.  * they happen, and reads commands from connections one spawn-request's 
  4.  * worth at a time. 
  5.  * 
  6.  * @throws MethodAndArgsCaller in a child process when a main() should 
  7.  * be executed. 
  8.  */  
  9. private static void runSelectLoopMode() throws MethodAndArgsCaller {  
  10.     ArrayList<FileDescriptor> fds = new ArrayList();  
  11.     ArrayList<ZygoteConnection> peers = new ArrayList();  
  12.     FileDescriptor[] fdArray = new FileDescriptor[4];  
  13.   
  14.     fds.add(sServerSocket.getFileDescriptor());  
  15.     peers.add(null);  
  16.   
  17.     int loopCount = GC_LOOP_COUNT;  
  18.     while (true) {  
  19.         int index;  
  20.   
  21.         /* 
  22.          * Call gc() before we block in select(). 
  23.          * It's work that has to be done anyway, and it's better 
  24.          * to avoid making every child do it.  It will also 
  25.          * madvise() any free memory as a side-effect. 
  26.          * 
  27.          * Don't call it every time, because walking the entire 
  28.          * heap is a lot of overhead to free a few hundred bytes. 
  29.          */  
  30.         if (loopCount <= 0) {  
  31.             gc();  
  32.             loopCount = GC_LOOP_COUNT;  
  33.         } else {  
  34.             loopCount--;  
  35.         }  
  36.   
  37.   
  38.         try {  
  39.             fdArray = fds.toArray(fdArray);  
  40.             index = selectReadable(fdArray);  
  41.         } catch (IOException ex) {  
  42.             throw new RuntimeException("Error in select()", ex);  
  43.         }  
  44.   
  45.         if (index < 0) {  
  46.             throw new RuntimeException("Error in select()");  
  47.         } else if (index == 0) {  
  48.             ZygoteConnection newPeer = acceptCommandPeer();  
  49.             peers.add(newPeer);  
  50.             fds.add(newPeer.getFileDesciptor());  
  51.         } else {  
  52.             boolean done;  
  53.             done = peers.get(index).runOnce();  
  54.   
  55.             if (done) {  
  56.                 peers.remove(index);  
  57.                 fds.remove(index);  
  58.             }  
  59.         }  
  60.     }  
  61. }  

runSelectLoopMode等待 ActivityManagerService发送请求过来,最后调用ZygoteConnection.runOncef fork一个进程来运行应用程序。
到这里zygote就启动完成了,在它fork出来的SystemServer会负责一些其它关键服务的初始化,而他自己则等待ActivityManagerService的请求,为一个新的应用程序fork出 一个子进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值