zoukankan      html  css  js  c++  java
  • Android系统进程Zygote启动过程的源代码分析

     

    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进程的脚本命令:

     

    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 view p c
     
    1.关键字service: 告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。

     

    2.socket关键字:  表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具体可以参考前面一篇文章Android学习启动篇提到的一书《Linux内核源代码情景分析》的第七章--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。

    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

     

    1. int main(int argc,constchar*const argv[])
    2. {
    3. // These are global variables in ProcessState.cpp
    4. AppRuntime runtime;
    5. .....
    6. // Next arg is parent directory
    7. if(i < argc){
    8. runtime.mParentDir = argv[i++];
    9. }
    10. // Next arg is startup classname or "--zygote"
    11. if(i < argc){
    12. arg = argv[i++];
    13. if(0== strcmp("--zygote", arg)){
    14. bool startSystemServer =(i < argc)?
    15. strcmp(argv[i],"--start-system-server")==0:false;
    16. setArgv0(argv0,"zygote");
    17. set_process_name("zygote");
    18. runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
    19. }else{
    20.          ......
    21. }
    22. }
    23. }
     
    这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。当AppRuntime对象创建时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将this指针保存在静态全局变量gCurRuntime中,这样,当其它地方需要使用这个AppRuntime对象时,就可以通过同一个文件中的这个函数来获取这个对象的指针,回到上面的main函数中,由于我们在init.rc文件中,设置了app_process启动参数--zygote和--start-system-server,因此,在main函数里面,最终会执行下面语句:
    1. runtime.start("com.android.internal.os.ZygoteInit",startSystemServer); 
     

    Step 2. AndroidRuntime.start : frameworks/base/core/jni/AndroidRuntime.cpp plain 

     

    1. /*
    2. * Start the Android runtime. This involves starting the virtual machine
    3. * and calling the "static void main(String[] args)" method in the class
    4. * named by "className".
    5. *
    6. * Passes the main function two arguments, the class name and the specified
    7. * options string.
    8. */
    9. voidAndroidRuntime::start(constchar* className,constchar* options)
    10. {
    11. ....
    12. /* start the virtual machine */
    13. JNIEnv* env;
    14. if(startVm(&mJavaVM,&env)!=0){
    15. return;
    16. }
    17. onVmCreated(env);
    18. /*
    19. * Register android functions.
    20. */
    21. if(startReg(env)<0){
    22. LOGE("Unable to register all android natives ");
    23. return;
    24. }
    25. /*
    26. * We want to call main() with a String array with arguments in it.
    27. * At present we have two arguments, the class name and an option string.
    28. * Create an array to hold them.
    29. */
    30. jclass stringClass;
    31. jobjectArray strArray;
    32. jstring classNameStr;
    33. jstring optionsStr;
    34. stringClass = env->FindClass("java/lang/String");
    35. assert(stringClass != NULL);
    36. strArray = env->NewObjectArray(2, stringClass, NULL);
    37. assert(strArray != NULL);
    38. classNameStr = env->NewStringUTF(className);
    39. assert(classNameStr != NULL);
    40. env->SetObjectArrayElement(strArray,0, classNameStr);
    41. optionsStr = env->NewStringUTF(options);
    42. env->SetObjectArrayElement(strArray,1, optionsStr);
    43. /*
    44. * Start VM. This thread becomes the main thread of the VM, and will
    45. * not return until the VM exits.
    46. */
    47. char* slashClassName = toSlashClassName(className);
    48. jclass startClass = env->FindClass(slashClassName);
    49. if(startClass == NULL){
    50. LOGE("JavaVM unable to locate class '%s' ", slashClassName);
    51. /* keep going */
    52. }else{
    53. jmethodID startMeth = env->GetStaticMethodID(startClass,"main",
    54. "([Ljava/lang/String;)V");
    55. if(startMeth == NULL){
    56. LOGE("JavaVM unable to find main() in '%s' ", className);
    57. /* keep going */
    58. }else{
    59. env->CallStaticVoidMethod(startClass, startMeth, strArray);
    60. }
    61. }
    62. free(slashClassName);
    63. }

    这个函数的作用是启动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

     

    1. publicclassZygoteInit{
    2. ......
    3. publicstaticvoid main(String argv[]){
    4. try{
    5. ......
    6. registerZygoteSocket();
    7. ......
    8. ......
    9. if(argv[1].equals("true")){
    10. startSystemServer();
    11. }elseif(!argv[1].equals("false")){
    12. ......
    13. }
    14. ......
    15. if(ZYGOTE_FORK_MODE){
    16. ......
    17. }else{
    18. runSelectLoopMode();
    19. }
    20. ......
    21. }catch(MethodAndArgsCaller caller){
    22. ......
    23. }catch(RuntimeException ex){
    24. ......
    25. }
    26. }
    27. ......
    28. }view plai copy
     
    它主要作了三件事情
    1. 调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯,
    2. 调用startSystemServer函数来启动SystemServer组件,
    3. 调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。
     
     
    Step 4. ZygoteInit.registerZygoteSocket : frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    1. publicclassZygoteInit{
    2. ......
    3. privatestaticfinalString ANDROID_SOCKET_ENV ="ANDROID_SOCKET_zygote";
    4. /**
    5. * Registers a server socket for zygote command connections
    6. *
    7. * @throws RuntimeException when open fails
    8. */
    9. privatestaticvoid registerZygoteSocket(){
    10. if(sServerSocket ==null){
    11. int fileDesc;
    12. try{
    13. String env =System.getenv(ANDROID_SOCKET_ENV);
    14. fileDesc =Integer.parseInt(env);
    15. }catch(RuntimeException ex){
    16. ......
    17. }
    18. try{
    19. sServerSocket =newLocalServerSocket(
    20. createFileDescriptor(fileDesc));
    21. }catch(IOException ex){
    22. .......
    23. }
    24. }
    25. }
    26. ......
    27. } view plain co
     
    这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到  view p
    Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer进程。
     

    Step 5. ZygoteInit.startSystemServer:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

     

    1. publicclassZygoteInit{
    2. ......
    3. privatestaticboolean startSystemServer()
    4. throwsMethodAndArgsCaller,RuntimeException{
    5. /* Hardcoded command line to start the system server */
    6. String args[]={
    7. "--setuid=1000",
    8. "--setgid=1000",
    9. "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
    10. "--capabilities=130104352,130104352",
    11. "--runtime-init",
    12. "--nice-name=system_server",
    13. "com.android.server.SystemServer",
    14. };
    15. ZygoteConnection.Arguments parsedArgs =null;
    16. int pid;
    17. try{
    18. parsedArgs =newZygoteConnection.Arguments(args);
    19. ......
    20. /* Request to fork the system server process */
    21. pid =Zygote.forkSystemServer(
    22. parsedArgs.uid, parsedArgs.gid,
    23. parsedArgs.gids, debugFlags,null,
    24. parsedArgs.permittedCapabilities,
    25. parsedArgs.effectiveCapabilities);
    26. }catch(IllegalArgumentException ex){
    27. ......
    28. }
    29. /* For child process */
    30. if(pid ==0){
    31. handleSystemServerProcess(parsedArgs);
    32. }
    33. returntrue;
    34. }
    35. ......
    36. }view plain cop
    这里我们可以看到,Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer系统进程,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。

     

            

    Step 6. ZygoteInit.handleSystemServerProcess 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

     

    1. publicclassZygoteInit{
    2. ......
    3. privatestaticvoid handleSystemServerProcess(
    4. ZygoteConnection.Arguments parsedArgs)
    5. throwsZygoteInit.MethodAndArgsCaller{
    6. closeServerSocket();
    7. /*
    8. * Pass the remaining arguments to SystemServer.
    9. * "--nice-name=system_server com.android.server.SystemServer"
    10. */
    11. RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
    12. /* should never reach here */
    13. }
    14. ......
    15. } view plain cop
    由于由Zygote进程创建的子进程会继承Zygote进程在中创建的Socket文件描述符,而这里的子进程SystemServer又不会用到它,因此,这里就调用closeServerSocket函数来关闭它。这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。

     

            

    Step 7. RuntimeInit.zygoteInit 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

     

    1. publicclassRuntimeInit{
    2. ......
    3. publicstaticfinalvoid zygoteInit(String[] argv)
    4. throwsZygoteInit.MethodAndArgsCaller{
    5. ......
    6. zygoteInitNative();
    7. ......
    8. // Remaining arguments are passed to the start class's static main
    9. String startClass = argv[curArg++];
    10. String[] startArgs =newString[argv.length - curArg];
    11. System.arraycopy(argv, curArg, startArgs,0, startArgs.length);
    12. invokeStaticMain(startClass, startArgs);
    13. }
    14. ......
    15. }
    这个函数会执行两个操作,一个是调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了,另一个是调用上面Step 5传进来的com.android.server.SystemServer类的main函数。

     

             

    Step 8. RuntimeInit.zygoteInitNative 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

     

    1. publicclassRuntimeInit{
    2. ......
    3. publicstaticfinalnativevoid zygoteInitNative();
    4. ......
    5. }view plai cop
    这里可以看出,函数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

     

    1. publicclassSystemServer
    2. {
    3. ......
    4. nativepublicstaticvoid init1(String[] args);
    5. ......
    6. publicstaticvoid main(String[] args){
    7. ......
    8. init1(args);
    9. ......
    10. }
    11. publicstaticfinalvoid init2(){
    12. Slog.i(TAG,"Entered the Android system server!");
    13. Thread thr =newServerThread();
    14. thr.setName("android.server.ServerThread");
    15. thr.start();
    16. }
    17. ......
    18. }view plain cop
    这里的main函数首先会执行JNI方法init1,然后init1会调用这里的init2函数,在init2函数里面,会创建一个ServerThread线程对象来执行一些系统关键服务的启动操作,例如PMS和AMS。这一步的具体执行过程可以参考Android应用程序安装过程源代码分析一文,这里就不再详述了。
    这里执行完成后,层层返回,最后回到上面的Step 3中的ZygoteInit.main函数中,接下来它就要调用runSelectLoopMode函数进入一个无限循环在前面Step 4中创建的socket接口上等待AMS请求创建新的应用程序进程了。
     

    Step 10. ZygoteInit.runSelectLoopMode : frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

     

    1. publicclassZygoteInit{
    2. ......
    3. privatestaticvoid runSelectLoopMode()throwsMethodAndArgsCaller{
    4. ArrayList<FileDescriptor> fds =newArrayList();
    5. ArrayList<ZygoteConnection> peers =newArrayList();
    6. FileDescriptor[] fdArray =newFileDescriptor[4];
    7. fds.add(sServerSocket.getFileDescriptor());
    8. peers.add(null);
    9. int loopCount = GC_LOOP_COUNT;
    10. while(true){
    11. int index;
    12. ......
    13. try{
    14. fdArray = fds.toArray(fdArray);
    15. index = selectReadable(fdArray);
    16. }catch(IOException ex){
    17. thrownewRuntimeException("Error in select()", ex);
    18. }
    19. if(index <0){
    20. thrownewRuntimeException("Error in select()");
    21. }elseif(index ==0){
    22. ZygoteConnection newPeer = ();
    23. peers.add(newPeer);
    24. fds.add(newPeer.getFileDesciptor());
    25. }else{
    26. boolean done;
    27. done = peers.get(index).runOnce();
    28. if(done){
    29. peers.remove(index);
    30. fds.remove(index);
    31. }
    32. }
    33. }
    34. }
    35. ......
    36. } view plai co
     
    这就是在等待AMS来连接这个Socket,然后调用ZygoteConnection.runOnce函数来创建新的应用程序,参见 --- Android应用程序进程启动过程的源代码分析
     
     
     

    关于笔者:

     
    微信公众号:编码安全
     
    微信:蕉下客
     
     
     
    邮箱: changle517318@sohu.om
     
     
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    知识共享时代,做一个优秀内容提供者。
    ------------------------------------------------------------------------------------------------------------------------------------------
     
  • 相关阅读:
    OSI七层模型详解 TCP/IP协议
    ZT 第一范式,第二范式,第三范式
    思杰20140522
    Correspondence / ˏkɔris'pɔndәns / dictionary10-800.doc
    闲着没事,贴贴图
    心情闲适,发几个tatanic的图
    005 Python 基础特性
    017 虚拟内存 64位及内存对其 3
    004 Python 文件操作 字典 自定义函数
    003 Python list 索引
  • 原文地址:https://www.cnblogs.com/jiaoxiake/p/6928309.html
Copyright © 2011-2022 走看看