精华内容
下载资源
问答
  • Zygote进程

    2021-07-13 09:35:04
    Zygote进程的作用主要有两个: 创建SystemServer进程;是用于管理整个Java framework层,包含ActivityManager,PowerManager等各种系统服务; 孵化其他应用程序进程; 3. Zygote的启动流程? Zygot.

    在这里插入图片描述

    1. Zygote是什么?

    Zygote是Android系统中的进程,由用户空间的第一个进程Init进程启动的,是Android系统运行的第一个AndroidRuntime进程,同时也是打通Native和Java的桥梁。

    2. Zygote的作用?

    Zygote进程的作用主要有两个:

    创建SystemServer进程;是用于管理整个Java framework层,包含ActivityManager,PowerManager等各种系统服务;
    孵化其他应用程序进程;

    3. Zygote的启动流程?

    Zygote进程是由Init进程解析init.zygote.rc文件启动的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygote。

    首先执行App_main.cpp的main()函数,在这里会执行以下步骤:

    1.解析命令参数,主要是–zygote 和–start-system-server。

    2.调用AppRuntime.start(“com.android.internal.os.ZygoteInit”,…),启动虚拟机,注册JNI函数;

    3.通过JNI调用ZygoteInit.java的main()方法,从这里开始进入Java的世界;

    运行Zygote的main方法,主要执行以下步骤:

    预加载 preloadClasses()、preloadResources()、preloadSharedLibraries()
    forkSystemServer,最终会调用SystemServer.java的main()方法;
    创建ZygoteService,进入runSelectLoop;

    4. Zygote需要注意的事项

    1.Zygote进行fork的时候要是单线程,为了避免造成死锁或者状态不一致等问题;
    2.Zygote的跨进程通信没有采用Binder机制,而是采用本地socket。

    5. 孵化应用进程这种事为什么不交给SystemServer来做,而专门设计一个Zygote?

    我们知道,应用在启动的时候需要做很多准备工作,包括启动虚拟机,加载各类系统资源等等,这些都是非常耗时的,如果能在zygote里就给这些必要的初始化工作做好,子进程在fork的时候就能直接共享,那么这样的话效率就会非常高。这个就是zygote存在的价值,这一点呢SystemServer是替代不了的,主要是因为SystemServer里跑了一堆系统服务,这些是不能继承到应用进程的。所以给SystemServer和应用进程里都要用到的资源抽出来单独放在一个进程里,也就是这的zygote进程,然后zygote进程再分别孵化出SystemServer进程和应用进程。

    6. Zygote的IPC通信机制为什么使用socket而不采用binder?

    主要原因是因为Zygote进行fork的时候要是单线程,父进程binder线程有锁,然后子进程的主线程一直在等其子线程(从父进程拷贝过来的子进程)的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁,所以fork不允许存在多线程。而非常巧的是Binder通讯偏偏就是多线程,所以干脆父进程(Zygote)这个时候就不使用binder线程。

    展开全文
  • Android进程-zygote进程

    2018-01-31 17:49:32
    一,zygote进程 zygote进程的父进程是init,zygote也是所有应用的父进程,也是system_server进程的父进程。   1.1 Zygote系统源码组成 1) Zygote.java(frameworks/base/core/java/com/android/internal/os/) ...

    一,zygote进程

    zygote进程的父进程是init,zygote也是所有应用的父进程,也是system_server进程的父进程。

     

    1.1  Zygote系统源码组成

    1)     Zygote.java(frameworks/base/core/java/com/android/internal/os/)

    提供访问vm的zygote接口,主要是包装Linux系统的fork,以 一个新的vm实例进程。

    2)     ZygoteConnection.java (frameworks/base/core/java/com/android/internal/os/)

    Zygote的socket连接管理及其参数解析,AMS建立应用进程的请求是通过socket发送命令参数给zygote。

    3)     ZygoteInit.java(frameworks/base/core/java/com/android/internal/os/)

    Zygote系统的main函数入口。

     

    1.2  Zygote的启动

    System/core/rootdir/init.rc中会把具体的zygote*.rc文件import进来:

    import /init.${ro.zygote}.rc

    这里根据不同的硬件平台加载不同的.rc,可以参看multilibbuild:http://blog.csdn.net/lin20044140410/article/details/79265521

     

    以init.zygote64.rc为例,启动命令如下:

    service zygote /system/bin/app_process64-Xzygote /system/bin --zygote --start-system-server

       class main

    socket zygotestream 660 root system

    其中的关键字service:通知init进程创建一个名为zygote的进程,此zygote进程要执行的程序路径是system/bin/app_process64,后面是传递给app_process程序的参数。

    关键字class:指定class类型是main。

    关键字socket:表示这个zygote进程需要一个名称为zygote的socket资源,    系统启动后,会在/dev/socket/ 目录下看到一个名为zygote的文件。

     

    App_process程序对应源码:frameworks/base/cmds/app_process/其中app_main.cpp的main函数是入口函数。

    1)具体分析启动脚本:

    在init.rc中,是以service的形式来启动zygote进程,在解析init.rc文件时,会调用service::start函数来启动zygote,也就是解析其中的service命令。具体代码:

    Android/system/core/init/service.cpp
    bool Service::Start() {
    ……
    pid_t pid = fork();
        if (pid == 0) {
            umask(077);
    
            for (const auto& ei : envvars_) {
                add_environment(ei.name.c_str(), ei.value.c_str());
            }
    
            for (const auto& si : sockets_) {
                int socket_type = ((si.type == "stream" ? SOCK_STREAM :
                                    (si.type == "dgram" ? SOCK_DGRAM :
                                     SOCK_SEQPACKET)));
                const char* socketcon =
                    !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
    
                int s = create_socket(si.name.c_str(), socket_type, si.perm,
                                      si.uid, si.gid, socketcon);
                if (s >= 0) {
                    PublishSocket(si.name, s);
                }
            }
    		
    	}
    }
    

    每个service命令都会让init进程调用fork函数来创建一个新的进程,在新的进程中会处理其中的socket选项,对于每个socket选项来说,都会通过函数create_socket来在/dev/socket/目录下创建一个文件,

    在看create_socket,调用函数socket()创建一个socket,使用文件描述符来描述这个socket。

    System/core/init/Util.cpp
    int create_socket(const char *name, int type, mode_t perm, uid_t uid,
                      gid_t gid, const char *socketcon){
        struct sockaddr_un addr;
        int fd, ret, savederrno;
    char *filecon;
    //创建一个socket,unix domain socket,
        fd = socket(PF_UNIX, type, 0);
        if (fd < 0) {
            ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
            return -1;
    }
    //为socket创建一个类型为AF_UNIX的socket地址addr。
        memset(&addr, 0 , sizeof(addr));
        addr.sun_family = AF_UNIX;
        snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
                 name);
    
    	ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
    	return fd;
    }
    

    接着看PublishSocket()函数,将指向socket的文件描述符fd,添加到环境变量中。

    System/core/init/Service.h
    #define ANDROID_SOCKET_ENV_PREFIX	"ANDROID_SOCKET_"
    #define ANDROID_SOCKET_DIR		"/dev/socket"
    
    System/core/init/Service.cpp
    void Service::PublishSocket(const std::string& name, int fd) const {
        std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
        std::string val = StringPrintf("%d", fd);
        add_environment(key.c_str(), val.c_str());
    
        /* make sure we don't close-on-exec */
        fcntl(fd, F_SETFD, 0);
    }
    

    后面都是通过环境变量ANDROID_SOCKET_socket来获取这个文件描述的值。

     

           2)zygote的入口函数main。

           功能是创建AppRuntime实例,然后调用AppRuntime的start()启动进程。

    Frameworks/base/cmds/app_process/App_main.cpp
    int main(int argc, char* const argv[]){
    //创建AppRuntime实例
    	AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    //解析启动参数
        bool zygote = false;
        bool startSystemServer = false;
        bool application = false;
        String8 niceName;
    String8 className;
        while (i < argc) {
            const char* arg = argv[i++];
            if (strcmp(arg, "--zygote") == 0) {
                zygote = true;
    //后面讲进程名字设置为niceName(zygote)
                niceName = ZYGOTE_NICE_NAME;
            } else if (strcmp(arg, "--start-system-server") == 0) {
                startSystemServer = true;
            } else if (strcmp(arg, "--application") == 0) {
                application = true;
            } else if (strncmp(arg, "--nice-name=", 12) == 0) {
                niceName.setTo(arg + 12);
            } else if (strncmp(arg, "--", 2) != 0) {
                className.setTo(arg);
                break;
            } else {
                --i;
                break;
            }
    }
        if (!niceName.isEmpty()) {
            runtime.setArgv0(niceName.string());
            set_process_name(niceName.string());
    }
    //启动zygote,第一个参数是一个className:
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        }
    }
    

    3)zygote的启动函数start()

           调用startVM在zygote中创建一个虚拟机实例。

    classAppRuntime : public AndroidRuntime…,AppRuntime继承自AndroidRuntime,runtime的start()方法调用的是AndroidRuntime中的定义。

    Frameworks/base/core/jni/AndroidRuntime.cpp
    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
    //启动虚拟机,其中mJavaVM是:JavaVM* mJavaVM;Java虚拟机指针变量,
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) {
            return;
        }
    onVmCreated(env);
    //用虚拟机实例注册jni函数。
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
    }
    //根据传入的参数className调用com.android.internal.os.ZygoteInit的main,启动zygote进程。
        char* slashClassName = toSlashClassName(className);
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
            /* keep going */
        } else {
            jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
                /* keep going */
            } else {
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
            }
        }
        free(slashClassName);
    }
    

    ZygoteInit.java的main()函数。

    Frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    public static void main(String argv[]) {
    	try {
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
        for (int i = 1; i < argv.length; i++) {
            if ("start-system-server".equals(argv[i])) {
                startSystemServer = true;
            } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                abiList = argv[i].substring(ABI_LIST_ARG.length());
            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
            	socketName = argv[i].substring(SOCKET_NAME_ARG.length());
        	}
    }
    //创建一个socket接口,
    	registerZygoteSocket(socketName);
    //预加载一些资源
    	preload();
    //启动systemServer组件
    	startSystemServer(abiList, socketName);
    //调用runSelectLoop,进入无线循环,在前面创建的socket接口上等待,等待新的到socket的连接发生,然后从连接中读取请求命令,以孵化新的进程。
    	runSelectLoop(abiList);
    closeServerSocket();
    } (MethodAndArgsCaller caller) {
    	caller.run();
    }
    }
    
    
    private static void registerZygoteSocket(String socketName) {
            if (sServerSocket == null) {
                int fileDesc;
    //通过环境变量ANDROID_SOCKET_zygote,获取/dev/socket/zygote文件的文件描述符,
                final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
                try {
                    String env = System.getenv(fullSocketName);
                    fileDesc = Integer.parseInt(env);
                } catch (RuntimeException ex) {
                    throw new RuntimeException(fullSocketName + " unset or invalid", ex);
                }
    //通过这个socket的文件描述符创建一个LocalServerSocket,然后监听这个socket。
                try {
                    FileDescriptor fd = new FileDescriptor();
                    fd.setInt$(fileDesc);
                    sServerSocket = new LocalServerSocket(fd);
                } catch (IOException ex) {
                    throw new RuntimeException(
                            "Error binding to local socket '" + fileDesc + "'", ex);
                }
            }
    }
    

    其中预加载资源主要是预装Framework的部分类和资源,分为两类:

    1)文本文件framework/base/preload-class中定义的类,这个文本文件是由framework/base/tools/preload子项目编译生成的。

    2)加载preload-resources,主要是framework/base/core/res/res/values/arrays.xml中定义的drawable资源,color资源,这些资源通常有个前缀preloaded_***


    4)跟zygote进程中的socket实现连接

    当启动一个应用时,AMS通过函数Process.start创建一个新的进程,Process.start会通过socket连接到zygote进程,并由zygote进程实现创建应用进程的功能。Process通过函数openZygoteSocketIfNeeded连接到zygote进程中的socket。

    Frameworks/base/core/java/android/os/Process.java
    static ZygoteState primaryZygoteState;
    private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    	primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
    return primaryZygoteState;
    }
    public static ZygoteState connect(String socketAddress) throws IOException {
        DataInputStream zygoteInputStream = null;
        BufferedWriter zygoteWriter = null;
    final LocalSocket zygoteSocket = new LocalSocket();
    try {
    //通过LocalSocketAddress实现LocalSocket到LocalServerSocket的连接。
         zygoteSocket.connect(new LocalSocketAddress(socketAddress,
                 LocalSocketAddress.Namespace.RESERVED));
    
         zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
         zygoteWriter = new BufferedWriter(new OutputStreamWriter(
                  zygoteSocket.getOutputStream()), 256);
         } catch (IOException ex) {
         try {
        	     zygoteSocket.close();
             } catch (IOException ignore) {
             }
           throw ex;
         }
    
       String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
       Log.i("Zygote", "Process: zygote socket opened, supported ABIS: " + abiListString);
    
       return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
                        Arrays.asList(abiListString.split(",")));
    }
    

    试着去打开socket,如果已经打来了就什么也不做。前面在zygoteInit.java中,提到通过registerZygoteSocket,创建了一个LocalServerSocket实例,这个LocalServerSocket类的构造函数中的参数是一个代表/dev/socket/zygote/文件的文件描述符,所以Process.java所在的进程只要能连接到LocalServerSocket,就可以通过LocalServerSocket中持有的socket文件描述符,实现跟zygote进程通信。在执行LocalSocket.connect()时,创建的LocalSocketAddress实现了到LocalServerSocket的连接,其中LocalSocket就是连接到zygote进程的本地对象,ZygoteState是对这个实现的一个封装,Process.java中实际是通过ZygoteState中输出流BufferedWriter writer往socket中写入请求命令的。


    接下来Zygote进程的runSelectLoop()循环中,会接收到创建新的应用进程的请求,

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    
            ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
            ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    
     fds.add(sServerSocket.getFileDescriptor());
    
     while (true) {
    
                StructPollfd[] pollFds = new StructPollfd[fds.size()];
                for (int i = 0; i < pollFds.length; ++i) {
                    pollFds[i] = new StructPollfd();
                    pollFds[i].fd = fds.get(i);
                    pollFds[i].events = (short) POLLIN;
                }
                try {
                    Os.poll(pollFds, -1);
                } catch (ErrnoException ex) {
                    throw new RuntimeException("poll failed", ex);
                }
                for (int i = pollFds.length - 1; i >= 0; --i) {
                    if ((pollFds[i].revents & POLLIN) == 0) {
                        continue;
                    }
                    if (i == 0) {
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        fds.add(newPeer.getFileDesciptor());
                    } else {
                        boolean done = peers.get(i).runOnce();
                        if (done) {
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                }
    
     }
    
    }

    其中zygoteConnection中的runOnce()函数处理创建应用进程的请求。

    AMS请求zygote创建一个进程的过程大概是:

    1)AMS调用startProcessLocked函数

    2)Process.java中的start方法被调用

    3)Process.java中的startViaZygote方法被调用,在这个函数中把启动参数存入列表ArrayList<String> argsForZygote

    4)构造一个LocalSocket类型的本地socket接口

    5)通过该LocalSocket对象构造一个BufferedWriter对象

    6)通过BufferedWrite对象把argsForZygote列表中的参数传递给zygote中的LocalServerSocket对象。

    7)在zygote端调用Zygote.forkAndSpecialize()汗水和孕育一个新的应用进程。



    展开全文
  • Zygote进程启动流程

    2020-01-17 16:49:43
    博客同步至github博客:Zygote进程启动流程 使用到的相关源码:https://github.com/JesusYoung/AndroidResourceCode9.0/tree/master 基于Android 9.0 1、Zygote进程 Zygote是在init进程启动时创建的,它又称为孵化器...

    博客同步至github博客:Zygote进程启动流程

    使用到的相关源码:https://github.com/JesusYoung/AndroidResourceCode9.0/tree/master

    基于Android 9.0

    1、Zygote进程

    Zygote是在init进程启动时创建的,它又称为孵化器,它可以通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程,并且,Zygote进程在启动的时候会创建DVM或者ART,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本;

    2、Zygote进程启动流程

    2.1、Init进程调用

    2.1.1、解析配置参数

    Init进程启动之后,解析init.rc配置文件,执行其配置,其中有启动Zygote进程的参数配置,在app_main.cpp的main()方法中,先解析参数,例如在前面解析.rc文件时添加的参数“–zygote、----start-system-server”等,初始化各种标识位;

    int main(int argc, char* const argv[]) {
    	...
      ++i;  // Skip unused "parent dir" argument.
      while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
          zygote = true;
          niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
          startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
          application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
          niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
          className.setTo(arg);
          break;
        } else {
          --i;
          break;
        }
      }
      ...
    }
    

    2.1.2、启动Dalvik虚拟机

    接着判断className是否为空,在Zygote模式下,调用maybeCreateDalvikCache()函数创建Dalvik虚拟机缓存,添加启动systemServer的参数标识;

    int main(int argc, char* const argv[]) {
    	...
    	if (!className.isEmpty()) {
        ...
      } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();
        if (startSystemServer) {
          args.add(String8("start-system-server"));
        }
        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
          LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY);
          return 11;
        }
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);
        // In zygote mode, pass all remaining arguments to the zygote main() method.
        // 在Zygote模式下,将剩余的参数全部传递过去
        for (; i < argc; ++i) {
          args.add(String8(argv[i]));
        }
        ...
    }
    

    2.2、启动Zygote

    2.2.1、创建AppRunTime对象

    在main()函数中创建了AppRunTime对象,AppRunTime对象继承自AndroidRunTime类;

    int main(int argc, char* const argv[]) {
      ...
      AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
      ...
    }
    
    class AppRuntime : public AndroidRuntime {
      public:
      AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength) , mClass(NULL) {
        }
      ...
    }
    

    2.2.2、AppRunTime启动Zygote

    随后调用AppRunTime类的start()方法来启动Zygote进程,在前面判断中得知zygote参数为true;

    if (zygote) {
      runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
      runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
      ...
    }
    

    AppRunTime类继承自AndroidRunTime类,AppRunTime类并没有重载start()方法,所以这里执行的是AndroidRunnTime类的start()方法;

    2.2.3、注册JNI

    首先会初始化一些环境rootDir等,然后会启动虚拟机,调用startReg()函数向虚拟机注册Android Native方法;

    拿到前面传入的类名,即com.android.internal.os.ZygoteInit,通过JNI调用其main()方法,因为此处为C代码,而ZygoteInit为Java类,所以调用时需要使用JNI方式去调用,此时,正式从C层进入Java层;

    class AppRuntime : public AndroidRuntime {}
    
    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
      ...
      // 启动虚拟机
      if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
      }
      ...
      // 向虚拟机注册Android Native方法
      if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
      }
      ...
      char* slashClassName = toSlashClassName(className != NULL ? className : "");
      jclass startClass = env->FindClass(slashClassName);
      if (startClass == NULL) {
        ...
      } else {
        // 找到main()方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
          ...
        } else {
          // 调用ZygoteInit类的main()方法
          env->CallStaticVoidMethod(startClass, startMeth, strArray);
          #if 0
          if (env->ExceptionCheck())
            threadExitUncaughtException(env);
          #endif
        }
      }
      ...
    }
    

    2.2.4、启动进入Java层Zygote

    Zygote进程启动,在ZygoteInit的main()方法中,通过调用ZygoteHooks类的startZygoteNoThreadCreation()函数来抛出异常,标识Zygote进程已经启动;

    public static void main(String argv[]) {
      ZygoteServer zygoteServer = new ZygoteServer();
      // Mark zygote start. This ensures that thread creation will throw
      // an error.
      ZygoteHooks.startZygoteNoThreadCreation();
      ...
    }
    

    2.3、创建Zygote进程Socket

    2.3.1、创建服务端socket

    在ZygoteInit的main()函数中,创建了ZygoteServer对象,作为Zygote进程的socket通信的服务端,名为zygote,用来接收SystemServer进程向Zygote进程发来的请求,例如AMS向Zygote进程请求创建新应用等,接着调用runSelectLoop()来等待SystemServer进程发来的请求;

    public static void main(String argv[]) {
      ZygoteServer zygoteServer = new ZygoteServer();
      ...
      try {
        ...
        zygoteServer.registerServerSocketFromEnv(socketName);
        ...
        caller = zygoteServer.runSelectLoop(abiList);
      }
      ...
      if (caller != null) {
        caller.run();
      }
    }
    
    // ZygoteServer 
    void registerServerSocketFromEnv(String socketName) {
      if (mServerSocket == null) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
          String env = System.getenv(fullSocketName);
          fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
          throw new RuntimeException(fullSocketName + " unset or invalid", ex);
        }
        try {
          FileDescriptor fd = new FileDescriptor();
          fd.setInt$(fileDesc);
          mServerSocket = new LocalServerSocket(fd);
          mCloseSocketFd = true;
        } catch (IOException ex) {
          throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
        }
      }
    }
    

    2.3.2、执行客户端请求

    轮询客户端Socket消息,当客户端有新消息到来时,创建一个新的连接去执行客户端发来的请求,例如AMS请求创建新的进程;

    新建一个peers列表,用于存储每个客户端的连接,将fd数据转存到poolFds中,遍历,当i=0时表示有客户端与服务端连接成功,此时执行acceptCommandPeer()方法拿到新的连接,并将其存入到peers集合中,当i>0时,表示客户端在向服务端传输数据,从peers中拿出与客户端的连接,执行processOneCommand()函数得到一个Runnable对象,如果是fork子进程并且任务不为null则返回该Runnable对象,在main()函数中,如果该对象不为空,就去执行其run()方法;

    Runnable runSelectLoop(String abiList) {
      ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
      ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
      fds.add(mServerSocket.getFileDescriptor());
      peers.add(null);
      while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
          pollFds[i] = new StructPollfd();
          pollFds[i].fd = fds.get(i);
          pollFds[i].events = (short) POLLIN;
        }
        ...
        for (int i = pollFds.length - 1; i >= 0; --i) {
          ...
          if (i == 0) {
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            peers.add(newPeer);
            fds.add(newPeer.getFileDesciptor());
          } else {
            try {
              ZygoteConnection connection = peers.get(i);
              final Runnable command = connection.processOneCommand(this);
              if (mIsForkChild) {
                // We're in the child. We should always have a command to run at this
                // stage if processOneCommand hasn't called "exec".
                if (command == null) {
                  throw new IllegalStateException("command == null");
                }
                return command;
              } else {
                // We're in the server - we should never have any commands to run.
                if (command != null) {
                  throw new IllegalStateException("command != null");
                }
                // We don't know whether the remote side of the socket was closed or
                // not until we attempt to read from it from processOneCommand. This shows up as
                // a regular POLLIN event in our regular processing loop.
                if (connection.isClosedByPeer()) {
                  connection.closeSocket();
                  peers.remove(i);
                  fds.remove(i);
                }
              }
            }
            ...
          }
        }
      }
    }
    

    执行processOneCommand()方法时,创建fork子进程的Runnable对象,如果是在父进程中,则返回null,子进程中则会返回fork子进程的Runnable对象,去执行fork操作,并且清除掉fork过来的父进程中的socket信息;

    Runnable processOneCommand(ZygoteServer zygoteServer) {
      ...
      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                                     parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, 
                                     parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, 
                                     fdsToIgnore, parsedArgs.startChildZygote,
                                     parsedArgs.instructionSet, parsedArgs.appDataDir);
      try {
        if (pid == 0) {
          // in child
          zygoteServer.setForkChild();
          zygoteServer.closeServerSocket();
          IoUtils.closeQuietly(serverPipeFd);
          serverPipeFd = null;
          return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.startChildZygote);
        } else {
          // In the parent. A pid < 0 indicates a failure and will be handled in
          // handleParentProc.
          IoUtils.closeQuietly(childPipeFd);
          childPipeFd = null;
          handleParentProc(pid, descriptors, serverPipeFd);
          return null;
        }
        ...
    }
    

    2.4、启动SystemServer

    Zygote进程启动后,执行ZygoteInit类的main()方法,启动会调用forkSystemServer()方法去通过fork自身的方式去创建SystemServer进程;

    public static void main(String argv[]) {
    	...
      try {
      	...
        if (startSystemServer) {
          Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
          // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
          // child (system_server) process.
          if (r != null) {
            r.run();
            return;
          }
        }
        ...
      }
      ...
    }
    
    展开全文
  • 文章目录Android zygote 进程启动分析前言概述zygote 进程启动zygote 进程入口AppRuntim.startAppRuntime.startVmAppRuntime.startRegZygoteInit.mainZygoteInit.registerZygoteSocketZygoteInit.preloadZygoteInit....

    Android zygote 进程启动分析

    前言

    zygote 进程是 Android 系统中第一个拥有 Java 运行环境的进程,它由用户空间 1 号进程 init 进程通过解析 init.rc 文件创建,从 init 进程 fork 而来。从 zygote(受精卵)这个富含生物意义的名字可以知道,它是一个孵化器。Android 系统中所有运行在 Java 虚拟机中的系统服务以及应用均由 zygote 进程孵化而来。

    理解 zygote 进程的启动过程以及所做的工作,将为理解 Java 层系统服务以及所有应用的进程启动流程打下基础。

    概述

    zygote 通过克隆(fork)的方式创建子进程,fork 出来的子进程将继承父进程的所有资源,基于这个特性,zygote 进程在启动过程将创建 Java ART 虚拟机,预加载一个 Java 进程需要的所有系统资源,之后子进程被创建后,就可以直接使用这些资源运行了。

    自 Android 5.0 系统开始,zygote 不再是一个进程,而是两个进程,一个是 32 位 zygote,负责孵化 32 位进程(为了兼容使用了 armeabi 和 armeabi-v7a 等 32 位架构的本地动态库的应用),另一个是 64 位 zygote 进程,负责孵化 64 位应用进程(可加载 arm64-v8a 等 64 位架构本地库)。

    zygote 进程主要做了如下工作:

    1. 创建虚拟机,加载系统 Java 类以及注册系统类所依赖的 JNI 方法;
    2. 预加载应用程序进程所需的 drawable 和 color 资源,准备 WebView 和 OpenGL;
    3. 创建 socket 服务端,以便接收和处理创建应用进程的请求;
    4. 启动 system_server 服务进程,用于承载整个 framework 层运行的系统服务;
    5. 待命以随即处理到来的任务请求。

    参考相关资料,对 Android 6.0.1 系统中 zygote 进程启动关键流程进行分析。

    zygote 进程启动

    zygote 进程由 init 解析 init.rc 文件启动,首先看一下启动 zygote 的 rc 文件内容:

    32 位 zygote 启动内容在 init.zygote32.rc 文件中,64 位 zygote 启动内容在 init.zygote64.rc 中:

    提示:自 Android 9.0 系统开始,两个 zygote 启动配置放在一个文件中:init.zygote64_32.rc。

    # init.zygote32.rc
    
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart media
        onrestart restart netd
        writepid /dev/cpuset/foreground/tasks
    
    # init.zygote64.rc
    
    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
        class main
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart media
        onrestart restart netd
        writepid /dev/cpuset/foreground/tasks
    

    两者的唯一区别只在于可执行文件的不同,/system/bin/app_process/system/bin/app_process64

    zygote 将在如下情况下重启:

    1. servicemanager 进程死亡(启动配置中包含 onrestart restart zygote);
    2. surfaceflinger 进程死亡(启动配置中包含 onrestart restart zygote);
    3. Zygote 死亡(启动配置中为非 oneshot);
    4. system_server 进程死亡;

    zygote 进程入口

    zygote 可执行文件 app_process 的实现代码在 frameworks/base/cmds/app_process/app_main.cpp 中,入口为 main 函数:

    // app_main.cpp
    
    // ...
    #if defined(__LP64__)
    // 如果为 64 位进程,则进程名为 "zygote64",否则为 "zygote"
    static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
    static const char ZYGOTE_NICE_NAME[] = "zygote64";
    #else
    static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
    static const char ZYGOTE_NICE_NAME[] = "zygote";
    #endif
    
    int main(int argc, char* const argv[])
    {
      if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
        // 旧版内核不识别 PR_SET_NO_NEW_PRIVS,将返回 EINVAL,避免在旧版内核上死掉
        if (errno != EINVAL) {
          LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
          return 12;
        }
      }
    
      // argv[0] = "/system/bin/app_process"
      AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
      // 跳过 argv[0] 参数
      argc--;
      argv++;
    
      // 直到遇到 '-' 或第一个非 '-' 的参数为止的所有内容都将提供给虚拟机作为 options。
      //
      // --zygote:             启动到 zygote 模式
      // --start-system-server:启动 system server
      // --application:	    以应用程序模式启动 (独立启动, 非 zygote)
      // --nice-name:	    给进程起一个好名字
      //
      // 对于非 zygote 启动,这些参数后面将是主类名,所有其余的参数都传递给此类的 main 方法;
      // 对于 zygote 启动,所有剩余的参数都传递给 zygote 的 main 方法。
    
      int i;
      for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
          break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
          ++i;
          break;
        }
        runtime.addOption(strdup(argv[i]));
      }
    
      bool zygote = false;
      bool startSystemServer = false;
      bool application = false;
      String8 niceName;
      String8 className;
    
      ++i;
      while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
          zygote = true;
          niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
          startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
          application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
          niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
          className.setTo(arg);
          break;
        } else {
          --i;
          break;
        }
      }
    
      Vector<String8> args;
      if (!className.isEmpty()) {
        // 没有处于 zygote 模式
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
      } else {
        // className 为空,处于 zygote 模式
    
        // 创建 /data/dalvik-cache/ 目录
        maybeCreateDalvikCache();
    
        if (startSystemServer) {
          args.add(String8("start-system-server"));
        }
    
        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
          LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
            ABI_LIST_PROPERTY);
          return 11;
        }
    
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        // 获取支持的 abi 列表
        args.add(abiFlag);
    
        // 在 zygote 模式下,将所有剩余参数传递给 zygote 的 main() 方法。
        for (; i < argc; ++i) {
          args.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);
      } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
      } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
      }
    }
    

    AppRuntime.main 函数做了如下工作:

    1. 创建了 AppRuntime 对象,传入虚拟机所需的选项;
    2. 解析 init.rc 文件的 zygote 启动参数;
    3. 调用 AppRuntime.start 函数,根据启动 zygote 还是命令行(className),进入 ZygoteInit 或者 RuntimeInit 参数分支。

    提示:app_process 可使用命令行调用,启动一个 Java 类,并调用 main 方法,此时有 className 参数,处于非 zygote 模式。

    格式:

    app_process [可选参数] 命令所在路径 启动的类名 [可选参数]
    

    示例:

    app_process -Djava.class.path=Hello.dex /data/local/ com.example.Hello
    

    AppRuntim.start

    下面进入 AppRuntimestart 函数中,以 ZygoteInit 参数分支为路径进行分析:

    // AndroidRuntime.cpp
    
    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
      ALOGD(">>>>>> START %s uid %d <<<<<<\n",
              className != NULL ? className : "(unknown)", getuid());
    
      static const String8 startSystemServer("start-system-server");
    
      for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
          const int LOG_BOOT_PROGRESS_START = 3000;
          LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
      }
    
      const char* rootDir = getenv("ANDROID_ROOT");
      if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
          LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
         }
         setenv("ANDROID_ROOT", rootDir, 1);
      }
    
      JniInvocation jni_invocation;
      jni_invocation.Init(NULL);
      JNIEnv* env;
      // 创建虚拟机
      if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
      }
      onVmCreated(env);
      // 注册系统类 JNI 方法
      if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
      }
      
      jclass stringClass;
      jobjectArray strArray;
      jstring classNameStr;
      
      stringClass = env->FindClass("java/lang/String");
      assert(stringClass != NULL);
      // Java: strArray = new String[options.size() + 1];
      strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
      assert(strArray != NULL);
      classNameStr = env->NewStringUTF(className);
      assert(classNameStr != NULL);
      // Java: strArray[0] = "com.android.internal.os.ZygoteInit";
      env->SetObjectArrayElement(strArray, 0, classNameStr);
      
      // 将相关参数收集至 options 中,下面会传递给 ZygoteInit
      // --start-system-server, --abi-list=arm64-v8a ...
      for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
      }
      
      // 转换为 JNI 格式类名:com/android/internal/os/ZygoteInit
      char* slashClassName = toSlashClassName(className);
      jclass startClass = env->FindClass(slashClassName);
      if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
      } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
           "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
          ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
          // 调用 ZygoteInit.main();
          env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
      }
      free(slashClassName);
      
      ALOGD("Shutting down VM\n");
      // 关闭 Java 虚拟机
      if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
      if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
    }
    

    上面的代码也比较清晰,工作如下:

    1. startVm 函数创建 ART 虚拟机;
    2. startReg 函数注册系统 JNI 方法;
    3. 收集 options 参数,调用并传递给 ZygoteInit.main()

    下面针对每个方法具体分析。

    AppRuntime.startVm

    // AndroidRuntime.cpp
    
    int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
    {
      JavaVMInitArgs initArgs;
    
      // ...
    
      bool checkJni = false;
      property_get("dalvik.vm.checkjni", propBuf, "");
      if (strcmp(propBuf, "true") == 0) {
        checkJni = true;
      } else if (strcmp(propBuf, "false") != 0) {
        property_get("ro.kernel.android.checkjni", propBuf, "");
        if (propBuf[0] == '1') {
          checkJni = true;
        }
      }
      ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
      if (checkJni) {
        /* 扩展的 JNI 检查 */
        addOption("-Xcheck:jni");
    
        /* 启用 -Xcheck:jni,它提供了 JNI 函数调用跟踪 */
        //addOption("-verbose:jni");
      }
    
      parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
                         "-Xzygote-max-boot-retry=");
    
      // ...
     
      property_get("dalvik.vm.execution-mode", propBuf, "");
      if (strcmp(propBuf, "int:portable") == 0) {
        executionMode = kEMIntPortable;
      } else if (strcmp(propBuf, "int:fast") == 0) {
        executionMode = kEMIntFast;
      } else if (strcmp(propBuf, "int:jit") == 0) {
        executionMode = kEMJitCompiler;
      }
    
      // ...
    
      // 默认的起始和最大堆大小,通常根据具体厂商硬件进行合适的配置
      parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
      parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
      
      parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
      parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
      parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
      parseRuntimeOption("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
    
      // ...
    
      // 确保有可预加载的类文件,preloaded-classes 中存放了所有需要被预加载的系统 Java 类
      if (!hasFile("/system/etc/preloaded-classes")) {
        ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n", strerror(errno));
        return -1;
      }
    
      // ... 省略数百行 addOption 相关语句 
    
      // 解析 fingerprint 信息并提供给运行时,ANR dump 信息将包含 fingerprint 信息且能够解析
      parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:");
    
      initArgs.version = JNI_VERSION_1_4;
      initArgs.options = mOptions.editArray();
      initArgs.nOptions = mOptions.size();
      initArgs.ignoreUnrecognized = JNI_FALSE;
    
      // 初始化虚拟机。JavaVM* 是基于进程的,而 JNIEnv* 是基于线程的,
      // 如果调用成功,表示虚拟机已就绪,可以开始 JNI 调用了。
      if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
      }
    
      return 0;
    }
    

    上述代码主要是为虚拟机初始化添加运行选项,最后调用 JNI_CreateJavaVM 创建虚拟机,下面就进入了虚拟机流程了,需要理解虚拟机时再探究其源码。

    下面回到上面 AppRuntime.start 函数,看 startReg 的实现。

    AppRuntime.startReg

    // AndroidRuntime.cpp
    
    #define NELEM(x) (sizeof(x)/sizeof(*(x))) 
    
    /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
    {
      // 设置 Thread 创建函数,用于支持 Android Native 层线程封装
      androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
    
      ALOGV("--- registering native functions ---\n");
    
      env->PushLocalFrame(200);
    
      // 注册 JNI 方法
      if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
      }
      env->PopLocalFrame(NULL);
    
      //createJavaThread("fubar", quickTest, (void*) "hello");
    
      return 0;
    }
    
    // AndroidRuntim.cpp
    
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
    
    static const RegJNIRec gRegJNI[] = {
      REG_JNI(register_com_android_internal_os_RuntimeInit),
      REG_JNI(register_android_os_SystemClock),
      REG_JNI(register_android_util_EventLog),
      REG_JNI(register_android_util_Log),
      REG_JNI(register_android_content_AssetManager),
      REG_JNI(register_android_content_StringBlock),
      // ... 省略数百行
      REG_JNI(register_android_animation_PropertyValuesHolder),
      REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
      REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
    };
    
    static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
    {
      for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
    #ifndef NDEBUG
          ALOGD("----------!!! %s failed to load\n", array[i].mName);
    #endif
          return -1;
        }
      }
      return 0;
    

    startReg 函数主要是注册系统类的 JNI 方法,使用 register_jni_procs 进行循环调用注册方法,每个 mProc 都指向 gRegJNI 数组里存放的结构体中的 mProc 函数指针,例如 register_com_android_internal_os_RuntimeInit,查看一下实现:

    static JNINativeMethod gMethods[] = {
      { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
      { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
      { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
    };
    
    int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
    {
      return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
          gMethods, NELEM(gMethods));
    }
    

    startReg 之后下面就是通过 env->CallStaticVoidMethod 启动 Zygoteinit.main 进入 Java 层了。

    ZygoteInit.main

    // ZygoteInit.java
    
    public static void main(String argv[]) {
      try {
        RuntimeInit.enableDdms();
        SamplingProfilerIntegration.start();
    
        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        for (int i = 1; i < argv.length; i++) {
          if ("start-system-server".equals(argv[i])) {
            startSystemServer = true;
          } else if (argv[i].startsWith(ABI_LIST_ARG)) {
            abiList = argv[i].substring(ABI_LIST_ARG.length());
          } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
            socketName = argv[i].substring(SOCKET_NAME_ARG.length());
          } else {
            throw new RuntimeException("Unknown command line argument: " + argv[i]);
          }
        }
    
        if (abiList == null) {
          throw new RuntimeException("No ABI list supplied.");
        }
    
        // 注册 socket 服务端
        registerZygoteSocket(socketName);
        EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
            SystemClock.uptimeMillis());
        // 预加载资源
        preload();
        EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
            SystemClock.uptimeMillis());
    
        SamplingProfilerIntegration.writeZygoteSnapshot();
    
        // 在启动后执行初始 gc
        gcAndFinalize();
    
        Trace.setTracingEnabled(false);
    
        if (startSystemServer) {
          // 启动 system_server
          startSystemServer(abiList, socketName);
        }
    
        Log.i(TAG, "Accepting command socket connections");
        // 启动 socket 循环
        runSelectLoop(abiList);
        closeServerSocket();
      } catch (MethodAndArgsCaller caller) {
        caller.run();
      } catch (RuntimeException ex) {
        Log.e(TAG, "Zygote died with exception", ex);
        closeServerSocket();
        throw ex;
      }
    }
    

    上述代码做了如下工作:

    1. 使用 registerZygoteSocket 注册 socket 服务端,为能够接收创建子进程的请求提供支持;
    2. 使用 preload() 预加载应用进程所需资源;
    3. 启动 system_server 服务进程;
    4. 启动 socket 循环,等待外部请求,随时响应处理。

    下面进入函数具体分析。

    ZygoteInit.registerZygoteSocket

    // ZygoteInit.java
    
    private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
    
    // ...
    
    private static void registerZygoteSocket(String socketName) {
      if (sServerSocket == null) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
          String env = System.getenv(fullSocketName);
          fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
          throw new RuntimeException(fullSocketName + " unset or invalid", ex);
        }
    
        try {
          FileDescriptor fd = new FileDescriptor();
          fd.setInt$(fileDesc);
          // 创建了本地 socket 服务端
          sServerSocket = new LocalServerSocket(fd);
        } catch (IOException ex) {
          throw new RuntimeException(
                "Error binding to local socket '" + fileDesc + "'", ex);
        }
      }
    }
    

    主是要创建了本地服务端 socket 对象,命名为 ANDROID_SOCKET_zygote

    ZygoteInit.preload

    // ZygoteInit.java
    
    static void preload() {
      Log.d(TAG, "begin preload");
      // 预加载 /system/etc/preloaded-classes 文件中的系统类
      preloadClasses();
      // 预加载 drawable 和 color 资源
      preloadResources();
      // 预加载 OpenGL
      preloadOpenGL();
      // 预加载共享库
      preloadSharedLibraries();
      // 预加载文本资源
      preloadTextResources();
      // WebView 相关初始化
      WebViewFactory.prepareWebViewInZygote();
      Log.d(TAG, "end preload");
    }
    
    private static void preloadSharedLibraries() {
      Log.i(TAG, "Preloading shared libraries...");
      System.loadLibrary("android");
      System.loadLibrary("compiler_rt");
      System.loadLibrary("jnigraphics");
    }
    
    private static void preloadOpenGL() {
      if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
        EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
      }
    }
    
    private static void preloadTextResources() {
      Hyphenator.init();
    }
    
    private static void preloadClasses() {
      final VMRuntime runtime = VMRuntime.getRuntime();
      InputStream is;
      try {
        is = new FileInputStream(PRELOADED_CLASSES);
      } catch (FileNotFoundException e) {
        Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
        return;
      }
    
      // ...
       
      try {
        BufferedReader br = new BufferedReader(new InputStreamReader(is), 256);
        int count = 0;
        String line;
        while ((line = br.readLine()) != null) {
          line = line.trim();
          if (line.startsWith("#") || line.equals("")) {
            continue;
          }
          try {
    	// 预加载类
            Class.forName(line, true, null);
            count++;
          } catch (ClassNotFoundException e) {
            Log.w(TAG, "Class not found for preloading: " + line);
          } catch (UnsatisfiedLinkError e) {
            Log.w(TAG, "Problem preloading " + line + ": " + e);
          } catch (Throwable t) {
            // ...
            throw new RuntimeException(t);
          }
        }
        Log.i(TAG, "...preloaded " + count + " classes in "
              + (SystemClock.uptimeMillis()-startTime) + "ms.");
      } catch (IOException e) {
        Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
      } finally {
        IoUtils.closeQuietly(is);
        runtime.setTargetHeapUtilization(defaultUtilization);
        // 使用已加载类填充 DexCaches
        runtime.preloadDexCaches();
        // ...
      }
    }
    
    private static void preloadResources() {
      final VMRuntime runtime = VMRuntime.getRuntime();
      try {
        mResources = Resources.getSystem();
        mResources.startPreloading();
        if (PRELOAD_RESOURCES) {
          Log.i(TAG, "Preloading resources...");
          long startTime = SystemClock.uptimeMillis();
          TypedArray ar = mResources.obtainTypedArray(
                  com.android.internal.R.array.preloaded_drawables);
          int N = preloadDrawables(runtime, ar);
          ar.recycle();
          Log.i(TAG, "...preloaded " + N + " resources in "
                  + (SystemClock.uptimeMillis()-startTime) + "ms.");
          startTime = SystemClock.uptimeMillis();
          ar = mResources.obtainTypedArray(
                  com.android.internal.R.array.preloaded_color_state_lists);
          N = preloadColorStateLists(runtime, ar);
          ar.recycle();
          Log.i(TAG, "...preloaded " + N + " resources in "
                  + (SystemClock.uptimeMillis()-startTime) + "ms.");
        }
        mResources.finishPreloading();
      } catch (RuntimeException e) {
        Log.w(TAG, "Failure preloading resources", e);
      }
    }
    
    private static int preloadColorStateLists(VMRuntime runtime, TypedArray ar) {
      int N = ar.length();
      for (int i=0; i<N; i++) {
        int id = ar.getResourceId(i, 0);
        if (id != 0) {
          if (mResources.getColorStateList(id, null) == null) {
            throw new IllegalArgumentException(
                    "Unable to find preloaded color resource #0x"
                    + Integer.toHexString(id)
                    + " (" + ar.getString(i) + ")");
          }
        }
      }
      return N;
    }
    
    private static int preloadDrawables(VMRuntime runtime, TypedArray ar) {
      int N = ar.length();
      for (int i=0; i<N; i++) {
        int id = ar.getResourceId(i, 0);
        if (id != 0) {
          if (mResources.getDrawable(id, null) == null) {
            throw new IllegalArgumentException(
                    "Unable to find preloaded drawable resource #0x"
                    + Integer.toHexString(id)
                    + " (" + ar.getString(i) + ")");
          }
        }
      }
      return N;
    }
    

    上面几乎把加载资源的所有代码都列了出来。

    预加载这些资源的目的是为了将资源提前放置在内存中,当创建子进程的时候,可以直接使用这些资源,而不必每次都重新加载一遍。

    ZygoteInit.startSystemServer

    // ZygoteInit.java
    
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
      long capabilities = posixCapabilitiesAsBits(
        OsConstants.CAP_BLOCK_SUSPEND,
        OsConstants.CAP_KILL,
        OsConstants.CAP_NET_ADMIN,
        OsConstants.CAP_NET_BIND_SERVICE,
        OsConstants.CAP_NET_BROADCAST,
        OsConstants.CAP_NET_RAW,
        OsConstants.CAP_SYS_MODULE,
        OsConstants.CAP_SYS_NICE,
        OsConstants.CAP_SYS_RESOURCE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG
      );
    
      String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
      };
      ZygoteConnection.Arguments parsedArgs = null;
      
      int pid;
      
      try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
      
        // fork 出 system_server 进程并使用相关参数设置进程信息
        pid = Zygote.forkSystemServer(
            parsedArgs.uid, parsedArgs.gid,
            parsedArgs.gids,
            parsedArgs.debugFlags,
            null,
            parsedArgs.permittedCapabilities,
            parsedArgs.effectiveCapabilities);
      } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
      }
      
      if (pid == 0) {
        // 进入子进程
        if (hasSecondZygote(abiList)) {
          // 等待另一个架构的 zygote 进程启动
          waitForSecondaryZygote(socketName);
        }
      
        // 处理 system_server 剩余工作
        handleSystemServerProcess(parsedArgs);
      }
      
      return true;
    }
    

    上面的代码使用 Zygote.forkSystemServer fork 出了子进程,然后将相关参数设置给子进程,例如其中的 uid=1000gid=1000,下面就进入 handleSystemServerProcess 方法,开始 system_server 的工作。

    ZygoteInit.runSelectLoop

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
      ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
      ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    
      fds.add(sServerSocket.getFileDescriptor());
      peers.add(null);
      while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
          pollFds[i] = new StructPollfd();
          pollFds[i].fd = fds.get(i);
          pollFds[i].events = (short) POLLIN;
        }
        try {
          // 监听 socket 连接,阻塞并等待描述符上的可读事件发生
          Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
          throw new RuntimeException("poll failed", ex);
        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
          if ((pollFds[i].revents & POLLIN) == 0) {
            continue;
          }
          if (i == 0) {
            // i = 0 表明还未添加收到的 socket 请求对象(sServerSocket.accept())
    
            // 创建连接对象:new ZygoteConnection(sServerSocket.accept(), abiList);
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            peers.add(newPeer);
            // 添加到 fds 列表中待处理(下次循环将进行 Os.poll 等待描述符可读)
            fds.add(newPeer.getFileDesciptor());
          } else {
            // i > 0 表示 socket 请求经过 Os.poll 表示已经可读,那么对请求进行处理
            boolean done = peers.get(i).runOnce();
            if (done) {
              // 处理完则移除
              peers.remove(i);
              fds.remove(i);
            }
          }
        }
      }
    }
    

    runSelectLoop 进入了无限循环,等待并对服务端 socket 接收到的请求进行处理,使用 runOnce 进行请求处理:

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    
      String args[];
      Arguments parsedArgs = null;
      FileDescriptor[] descriptors;
    
      try {
        // 解析 socket 客户端发送的命令列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
      } catch (IOException ex) {
        Log.w(TAG, "IOException on command socket " + ex.getMessage());
        closeSocket();
        return true;
      }
    
      if (args == null) {
        closeSocket();
        return true;
      }
    
      // ...
    
      int pid = -1;
      FileDescriptor childPipeFd = null;
      FileDescriptor serverPipeFd = null;
    
      try {
        // 创建参数封装对象
        parsedArgs = new Arguments(args);
    
        if (parsedArgs.abiListQuery) {
          return handleAbiListQuery();
        }
       
        // ...
    
        int [] fdsToClose = { -1, -1 };
    
        FileDescriptor fd = mSocket.getFileDescriptor();
    
        if (fd != null) {
          fdsToClose[0] = fd.getInt$();
        }
    
        fd = ZygoteInit.getServerSocketFileDescriptor();
    
        if (fd != null) {
          fdsToClose[1] = fd.getInt$();
        }
    
        fd = null;
    
        // 创建子进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
      } catch (ErrnoException ex) {
        logAndPrintError(newStderr, "Exception creating pipe", ex);
      } catch (IllegalArgumentException ex) {
        logAndPrintError(newStderr, "Invalid zygote arguments", ex);
      } catch (ZygoteSecurityException ex) {
        logAndPrintError(newStderr,
                "Zygote security policy prevents request: ", ex);
      }
    
      try {
        if (pid == 0) {
          // 进入子进程
          IoUtils.closeQuietly(serverPipeFd);
          serverPipeFd = null;
          // 处理子进程逻辑
          handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
          return true;
        } else {
          IoUtils.closeQuietly(childPipeFd);
          childPipeFd = null;
          // 父进程剩余工作
          return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
      } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
      }
    }
    

    handleChildProc 处理子进程:

    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
      closeSocket();
      // 关闭复制出来的服务端 socket
      ZygoteInit.closeServerSocket();
    
      if (descriptors != null) {
        try {
          Os.dup2(descriptors[0], STDIN_FILENO);
          Os.dup2(descriptors[1], STDOUT_FILENO);
          Os.dup2(descriptors[2], STDERR_FILENO);
    
          for (FileDescriptor fd: descriptors) {
              IoUtils.closeQuietly(fd);
          }
          newStderr = System.err;
        } catch (ErrnoException ex) {
          Log.e(TAG, "Error reopening stdio", ex);
        }
      }
    
      if (parsedArgs.niceName != null) {
        // 设置进程名字
        Process.setArgV0(parsedArgs.niceName);
      }
    
      Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
      if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);
      } else {
        // 会辗转调用到 ActivityThread.main 进入应用程序主流程
        // 内部会抛出一个 ZygoteInit.MethodAndArgsCaller 异常(为了清空调用栈),
        // 从而返回到上面 ZygoteInit 的 main 方法的 catch 语句块中执行
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
      }
    }
    

    当子进程 fork 出来后,处理子进程,关闭 socket 资源,之后进入应用程序进程主流程。

    整体流程图

    使用流程图表示 zygote 整个工作过程:

    zygote

    参考

    展开全文
  • zygote进程认识

    2018-05-08 13:53:50
    今天开始正式一个android得项目,学习了一下zygote进程PID为1的为init进程;PPID为1的为daemon进程,PID为38的即zygote进程,她也是由init(1号进程)启动的,而PPID为38的进程则为zygote的子进程,基本为应用程序...
  • Android6.0 Zygote进程

    千次阅读 2016-08-20 13:16:45
    Android Zygote进程
  • Zygote进程的创建过程(Android 8.1)

    万次阅读 2019-08-13 16:10:29
    本篇文章的内容中,我将要给大家介绍Android开发中最长见到的一个底层进程——Zygote进程,它是我们开发的所有APP进程的父进程。可以说,Android中所有的Java进程都是由Zygote进程fork出来的。 那面Zygote进程又是...
  • 【Android】【Zygote】Android Zygote进程
  • Zygote是由init进程启动的。 而在Android系统中,Dalvik/ART虚拟机、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程(孵化器)来创建的。 ...
  • 而在Android系统中也有这么一个“受精卵进程” – Zygote进程。 在Android系统中,Zygote进程是所有Android进程的父进程。它通过fork的形式,创建SystemServer进程和应用程序进程。而Zygote进程则是通过linux系统的...
  • Zygote进程的启动

    千次阅读 2015-12-10 11:32:56
    1. 系统启动时init进程会创建Zygote进程Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。 2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理...
  • Android系统的Zygote是一个C/S模型,Zygote进程作为服务端,其它进程作为客户端向它发出“孵化-fork”请求,而Zygote进程接收到这个请求后就“孵化-fork”出一个新的进程。 Zygote进程处于Native层创建。 核心源码...
  • init进程与zygote进程

    2017-11-06 11:33:41
    通过ps命令了解Android中运行的进程和android的守护...zygote进程生成系统服务器端和各种java应用程序进程。 init进程在所有系统中通常具有固定的pid值(pid=1),但启动其他进程时,不同系统赋予的pid值也有所不同。
  • Zygote进程启动过程

    2020-04-26 18:42:49
    Zygote 进程是在 init 进程启动时创建的,Zygote 的启动脚本在system/core/rootdir 目录下,这里不详细说 init 进程启动过程了,它可以简单描述为解析 init.rc ,启动相应的脚本 init.zygote32.rc 代码 #zygote...
  • android zygote 进程分析

    2019-02-28 16:35:58
    在 Android 系统中,所有的应用程序以及系统服务进程 SystemService 都是由 zygote 进程孕育 (fork) 出来的。 创建 java 虚拟机,加载系统资源 应用程序启动过程中负责 fork 出子进程 在 Android 应用程序启动时...
  • Zygote进程的启动流程

    2019-04-27 13:04:25
    Zygote进程被称为"进程孵化器",我们所有的应用进程,以及SystemServer进程都是由它创建的,Zygote进程是由init进程创建而来。 在系统启动脚本system/core/rootdir/init.rc文件中,可以看到启动Zygote进程的脚本命令...
  • Zygote进程详解

    千次阅读 2015-04-03 16:16:49
    Zygote进程是怎么启动的? Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统...
  • zygote进程fork子进程前言 前言 每个APP可能运行在一个进程,也可能在多个进程,这些进程拥有自己独立的资源;然而这些进程都是由Zygote进程fork出来的,再往前一步其实是system server进程使用LocalSocket去通知...
  • Android系统启动时,Init进程会把Zygote进程启动起来,而Zygote进程会把System Server进程启动起来。
  • Zygote进程的分析

    2018-01-12 09:35:32
    zygote进程的分析 1、init.zygote32.rc 3 2、app_main.cpp 4 3、ZygoteInit.java 5 4、registerZygoteSocket() 6 5、startSystemServer() 7 6、runSelectLoop() 8 6.1、ZygoteConnection.runOnce...
  • Android zygote 进程的启动过程分析

    千次阅读 2019-07-11 23:58:57
    zygote进程在 Android 开发中属于比较底层的内容,然而要透彻的理解 AMS、WMS 和 IPC 等,不可避免的要先理解zogyte进程,因此本文即作为对自己的学习记录,也想分享出来和遇到同样问题的读者交流。
  • 1. 系统启动时init进程会创建Zygote进程Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。 2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包...
  • Inite进程启动后,最重要的一个进程就是Zygote进程,Zygote是所有应用的鼻祖,SystemServer和其他Dalivik虚拟机进程都是由Zygote fork而来。 Zygote进程由app_process启动,Zygote是一个C/S模型,Zygote是服务端,...
  • Zygote进程启动流程分析 先说结论,zygote进程启动过程中主要做了下面这些事情: 启动DVM虚拟机 预加载部分资源,如一些通用类、通用资源、共享库等 启动system_server进程 创建一个ServerSocket,并进入死循环...
  • 开机启动 Zygote 进程

    2021-04-01 23:53:08
    Android - 开机启动 Zygote 进程 对应找到 /frameworks/base/cmds/app_process/app_main.cpp 源码文件中的 main 方法 int main(int argc, char* const argv[]) { // AppRuntime 继承 AndoirdRuntime AppRuntime ...
  • 在Android系统中,DVM(Dalvik虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器。它通过fork (复制进程)的形式来创建应用程序进程和SystemServer进程...
  • Init 进程孵化出 Zygote 进程Zygote 进程是 Android 系统的第一个 Java 进程 (即虚拟机进程),Zygote 是所有 Java 进程的父进程。 目录: 概述 Zygote 的启动过程 Java 层分析 总结 1. 概述 Zygote ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,857
精华内容 6,742
关键字:

zygote进程