• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

android8.1启动过程(六) zygote进程分析2

互联网 diligentman 1周前 (05-02) 6次浏览

 次部分承接上一篇文章https://blog.csdn.net/we1less/article/details/116139142?spm=1001.2014.3001.5501


registerServerSocket(socketName)  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

void registerServerSocket(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);
        } catch (IOException ex) {
            throw new RuntimeException(
                    "Error binding to local socket '" + fileDesc + "'", ex);
        }
    }
}
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

  【1】 拼接socker名称  ANDROID_SOCKET_zygote  

String env = System.getenv(fullSocketName);

  【2】得到socket的环境变量的值

mServerSocket = new LocalServerSocket(fd);

  【3】创建服务器端socket并将文件操作符作为参数传递进去  在zygote进程将systemserver进程启动后就会在你这个服务器端的socket上等待AMS请求zygote进程来创建新的进程

关于socket这里附上一个文章https://www.cnblogs.com/zijianlu/archive/2013/04/18/3028090.html具体可以参考看看


preload(bootTimingsTraceLog)  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
        ...
        preloadClasses();
        ...
        preloadResources();
        ...
        nativePreloadAppProcessHALs();
        ...
        preloadOpenGL();
        ...
        preloadSharedLibraries();
        ...
        preloadTextResources();
        ...
        warmUpJcaProviders();
        ...
    }

  【1】预加载位于/system/etc/preloaded-classes文件中的类

  【2】预加载drawble和color的资源信息AOSP/frameworks/base/core/res/res/values/arrays.xml   

           drawble   :    preloaded_drawables

           color    :    preloaded_color_state_lists

  【3】通过JNI调用,预加载底层相关的资源

  【4】预加载OpenGL资源

  【5】预加载共享库:"android","compiler_rt","jnigraphics"

  【6】预加载文本连接符资源

  【7】zygote中,内存共享进程

    通过【1】【2】步骤的预加载可以使继承自zygote的进程预加载系统文件从而使得进程启动更快


启动systemserver  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

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;
    }
}

  【1】forkSystemServer  父进程分支返回null 子进程分支返回  handleSystemServerProcess并返回回去最终调用了run()方法 关于具体systemserver启动会在后面单独开一篇文章去分析到这里只需要知道启动了systemserver就好

  【2】Zygote.forkSystemServer  其内部会调用nativeForkSystemServer方法,这个native方法最终会通过fork()方法创建当前进程的一个子进程  对于fork()方法这里给出一篇文章有兴趣的可以参考看看

  https://www.cnblogs.com/coolgestar02/archive/2011/04/28/2032018.html  总之fork函数最终在父进程的返回值是子进程的pid,而在子进程返回的则是0

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

runSelectLoop(abiList)   AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

Zygote完成了Java的初始工作后,便调用runSelectLoop来让自己无限循环等待。如果收到子孙后台的请求,它便会醒来为他们工作。

Runnable runSelectLoop(String abiList) {
    ...
    fds.add(mServerSocket.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);
            ...
        }
        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 {
                    try {
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);
                    ...
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                } catch (Exception e) {
                    ...
                }
            }
        }
    }
}

  【1】fds.add(mServerSocket.getFileDescriptor());  fds[0]为mServerSocket,即mServerSocket为位于zygote进程中的socket服务端

  【2】Os.poll(pollFds, -1);  查询轮训状态,当pollFdd有事件到来则往下执行,否则阻塞在这里

  【3】if (i == 0) {  ZygoteConnection newPeer = acceptCommandPeer(abiList);  peers.add(newPeer);  fds.add(newPeer.getFileDesciptor());  

           客户端第一次请求服务端,服务端调用accept与客户端建立连接,客户端在zygote以ZygoteConnection对象表示

  【4】else {   try {   ZygoteConnection connection = peers.get(i);   final Runnable command = connection.processOneCommand(this);   

          经过上个if操作后,客户端与服务端已经建立连接,并开始发送数据  peers.get(index)  取得发送数据客户端的  ZygoteConnection  对象  然后调用  processOneCommand(this)  方法来出具具体请求

          如果  i==0  表示说明服务端socket已经于客户端连接上了  换句话说就是当前zygote进程已经于AMS连接上了

          如果  i!=0  表示AMS向zygote进程发送一个创建应用进程的请求  再调用  processOneCommand(this)  方法fork出一个新的进程

  【5】fds.remove(i);  处理完则从fds中移除该文件描述符


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

在这里fork出一个子进程返回handleChildProc  父进程执行handleParentProc

pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
        parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
        parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
        parsedArgs.appDataDir);

try {
    if (pid == 0) {
        // in child
        zygoteServer.setForkChild();

        zygoteServer.closeServerSocket();
        IoUtils.closeQuietly(serverPipeFd);
        serverPipeFd = null;

        return handleChildProc(parsedArgs, descriptors, childPipeFd);
    } 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;
    }


程序员灯塔
转载请注明原文链接:android8.1启动过程(六) zygote进程分析2
喜欢 (0)