Android开发Android技术知识

Zygote 与服务进程的启动分析(Android P)

2019-01-06  本文已影响151人  SharryChoo

什么是 Zygote 进程

顾明思议, Zygote 是孵化器的意思, 在 Android 系统中, 所有的应用程序进程以及用来运行系统关键服务的 System 进程, 都是由 Zygote 创建的, 它就是孵化器进程

Zygote 进程什么时候启动

尽管 Zygote 进程非常重要, 但它其实并不是 Android 系统的第一个进程

Zygote 进程如何启动

上面了解到 Zygote 进程是在 init 进程读取了 init.zygote(xx).rc 脚本文件后启动的, 接下来我们先分析一下, 这个脚本中配置了什么

Zygote 启动脚本

这里选取 init.zygote32.rc 分析

// system/core/rootdir/init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    ......
    socket zygote stream 660 root system

简单的分析一下这个脚本文件

好的, 我们关注到, Zygote 的入口在 /system/bing/app_process 目录中, 接下来分析它的启动流程

Zygote 启动流程

/system/bing/app_process 目录下的 Zygote 进程入口 main 函数在 app_main.cpp 中

一) app_main.cpp 的 main 函数

// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    if (zygote) {
        // 若是 zygote 则调用了 AppRuntime 的 start 方法, AppRuntime 继承 AndroidRuntime
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        ......
    } else {
        ......
    }
}

可见 app_main.cpp 中的 main 方法, 将 Zygote 的启动分发给了 AndroidRuntime.start 中, 我们接着往下分析

// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ......
    // 1. 创建一个 Java 虚拟机
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 2. 构建用于调用 java main() 方法的字符串数组
    jclass stringClass;    // 描述 String.class
    jobjectArray strArray; // 描述 String[] 数组
    jstring classNameStr;  // 描述字符串对象
    // 创建 java 字符串数组
    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    // 从 app_main.cpp 中的 main 函数可知, className 为 "com.android.internal.os.ZygoteInit"
    classNameStr = env->NewStringUTF(className);
    // 2.2 将 ZygoteInit 的全限定类名导入
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    // 2.3 将 options 中的参数导入
    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);
    }

    // 3. 调用 ZygoteInti 中的 main 方法
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ......
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ......
        } else {
            // 调用了 ZygoteInti.main() 方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

    }
    ......
}

好的, 可以看到 Zygote 进程的启动调用了 AppRuntime.start 方法这个, 这个方法做了如下几件事情

好的, 至此 Zygote 进程的启动工作就转移到了 Java 中了, 我们看看 ZygoteInit 中做了什么

二) ZygoteInit 的 main 方法

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {
    
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        // 将 Zygote 标记为启动了
        ZygoteHooks.startZygoteNoThreadCreation();
        final Runnable caller;
        try { 
            // 用于判断在 Zygote 进程启动之后, 是否启动 SystemService 进程
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                // 若 argv 中包含 "start-system-server" 表示紧接着启动 SystemService 进程
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = 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]);
                }
            }
            // 1. 注册 Zygote 进程的 Socket, 用于跨进程建立连接
            zygoteServer.registerServerSocketFromEnv(socketName);
            // 2. 创建 SystemService 系统服务进程
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
                // r == null 说明当前是 Zygote 进程执行该 main 方法
                // r != null 说明当前是 SystemService 进程执行该 main 方法
                if (r != null) {
                    r.run();
                    return++;++
                }
            }
            // 3. 开启 Zygote 进程的死循环, 其他进程发送的进程创建请求
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            ......
        } finally {
            // 关闭
            zygoteServer.closeServerSocket();
        }
        ......
    }
    
}

可见 ZygoteInit 的 main 方法主要做了如下几件事情

接下来逐一分析

1. 创建 Zygote 进程的 Socket

// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
class ZygoteServer {

    private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
    
    /**
     * Listening socket that accepts new server connections.
     */
    private LocalServerSocket mServerSocket;
   
    void registerServerSocketFromEnv(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                // 获取环境变量的值 ANDROID_SOCKET_zygote
                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);
                // 以 fd 为参, 创建了一个 LocalServerSocket 实例对象
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                ......
            }
        }
    }
    
}

好的可以看到创建 Zygote 进程的 Socket 最终 new 了一个 LocalServerSocket, 并将它保存在 ZygoteServer 的成员变量 mServerSocket 中

2. 启动 SystemService 进程

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {

    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ......
        
        // 1. 构建系统服务进程的参数
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;
        int pid;
        try {
            // 2. 将 args 参数封装成 Arguments对象
            parsedArgs = new ZygoteConnection.Arguments(args);
            ......
           // 3. 调用 Zygote.forkSystemServer() 孵化系统服务进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            ......
        }
        // pid == 0 表示在新 fork 的子进程中调用(即系统服务进程)
        if (pid == 0) {
            ......
            // 处理系统服务进程的启动操作
            return handleSystemServerProcess(parsedArgs);
        }
        // 表示在 Zygote 进程调用, 返回 null
        return null;
    }

}

通过 Zygote 进程启动可知, SystemServer 进程在其启动过程中

这个放到后面分析, 我们先接着往下看

3. Zygote 进程的循环等待其他进程的连接请求

// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
class ZygoteServer {

    Runnable runSelectLoop(String abiList) {
        // Socket 的文件描述集合, 从上面 Zygote 的 Socket 创建可知, 在构造 Socket 实例时, 会传入其相应的文件描述
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();   
        // 与 Zygote 建立连接的集合
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        // 将当前 Zygote 进程的 Socket 文件描述添加进去
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);
        // 开启一个死循环
        while (true) {
            // 1. 通过 fds 持续的判断 Socket 中是否有数据可读
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                // 创建一个 StructPollfd 对象, 给相关属性赋值
                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 ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                // 2. i == 0 表示 其他进程通过 Socket 与当前 Zygote 进程建立了连接 
                if (i == 0) {
                    // 2.1 创建了一个连接对象加入 peers 缓存
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    // 2.2 从连接对象中获取文件描述符加入 fds 缓存
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    // 3. i > 0 执行子进程孵化
                    try {
                        // 获取连接对象
                        ZygoteConnection connection = peers.get(i);
                        // 调用 ZygoteConnection.processOneCommand 孵化进程
                        final Runnable command = connection.processOneCommand(this);
                        if (mIsForkChild) {
                            .......
                            return command;
                        } else {
                            ......
                            // 孵化结束, 移除这个请求
                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(i);
                                fds.remove(i);
                            }
                        }
                    } catch (Exception e) {
                        ......
                    } finally {
                        ......
                    }
                }
            }
        }
    }
    
}

好的, 可见 ZygoteServer 中, 会开启一个死循环

Zygote 启动流程图

至此 Zygote 的进程启动分析就结束了, 这里将上述代码翻译成时序图, 加深一下印象


image.png

系统服务进程的启动

上面在 Zygote 启动的过程中, 我们同时发起了 SystemServer 进程的启动, 先回顾一下

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {

    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ......
        
        // 1. 构建系统服务进程的参数
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;
        int pid;
        try {
            // 2. 将 args 参数封装成 Arguments对象
            parsedArgs = new ZygoteConnection.Arguments(args);
            ......
           // 3. 调用 Zygote.forkSystemServer() 孵化系统服务进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            ......
        }
        // pid == 0 表示在新 fork 的子进程中调用(即系统服务进程)
        if (pid == 0) {
            ......
            // 处理系统服务进程的启动操作
            return handleSystemServerProcess(parsedArgs);
        }
        // 表示在 Zygote 进程调用, 返回 null
        return null;
    }

}

通过 Zygote 进程启动可知, SystemServer 进程在其启动过程中

孵化 SystemServer 进程

接下来就分析一下 Zygote.forkSystemServer() 这个方法

public final class Zygote {
    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ......
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        ......
        return pid;
    }
    
    native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
            
}

可见 Zygote 中 forkSystemServer 将启动系统服务进程的工作转发到了 native 层去做, 我们继续追踪

// frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
namespace android {
    
    static jint com_android_internal_os_Zygote_nativeForkSystemServer(
            JNIEnv *env, jclass, uid_t uid, gid_t gid, jintArray gids,
            jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
            jlong effectiveCapabilities) {
        // 调用了 ForkAndSpecializeCommon, 来孵化这个系统进程
        pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                            runtime_flags, rlimits,
                                            permittedCapabilities, effectiveCapabilities,
                                            MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                            NULL, false, NULL, NULL);
        ......
        return pid;
    }
    
}

namespace {
    static pid_t ForkAndSpecializeCommon(......) {
        ......
        // fork 了一个 SystemService 进程
        pid_t pid = fork();
        ......
        return pid;
    }
}

可以看到, 最终会调用一个 fork 方法孵化一个进程, 孵化的过程就不去深究了, 我们主要关注 SystemServer 的启动操作

处理 SystemServer 的启动

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {
    
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
       
        if (parsedArgs.invokeWith != null) {
            ......
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                // 给这个设置类加载器
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
                Thread.currentThread().setContextClassLoader(cl);
            }
            // 将剩下参数传递给 zygoteInit 方法
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }
    
    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        
        // 调用了 commonInit() 设置 System 进程的时区和键盘布局等信息
        RuntimeInit.commonInit();
        // 初始化了 System 进程中的 Binder 线程池
        ZygoteInit.nativeZygoteInit();
        // 回调 main 方法
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
    
}

好的可以看到 ZygoteInit.handleSystemServerProcess 最终将 SystemServer 的启动, 转发到了 RuntimeInit.applicationInit 中去, 我们继续往下分析

public class RuntimeInit {

   protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ......
        // 将参数封装到 Arguments 对象中
        final Arguments args = new Arguments(argv);
        // 找寻 SystemService 进程的 main 函数入口, 并且回调它
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }
    
}

从 ZygoteInit.forkSystemServer 中 args 的构建可知, 这个 main 函数的入口其实在 "com.android.server.SystemServer" 中, 我们继续追踪下去

public final class SystemServer {

    private Context mSystemContext;
    private SystemServiceManager mSystemServiceManager;

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    
    private void run() {
        try {
            // 准备主线程的消息循环
            Looper.prepareMainLooper();
            ......
            // 1. 创建系统服务进程的上下文
            createSystemContext();
            // 2. 创建了一个 SystemServiceManager 的实例对象
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            ......
        } finally {
            ......
        }
        
        // 3. 启动系统服务
        try {
            // 启动系统辅助服务
            startBootstrapServices();
            // 启动系统核心服务
            startCoreServices();
            // 启动系统其他服务
            startOtherServices();
            ......
        } catch (Throwable ex) {
            ......
        } finally {
            ......
        }
        ......
        // 开启消息循环
        Looper.loop();
    }
    
    private void createSystemContext() {
        // 1.1 调用 ActivityThread.systemMain 获取一个 ActivityThread 实例
        ActivityThread activityThread = ActivityThread.systemMain();
        // 1.2 通过这个实例获取 Context 对象
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
        ......
    }
    
}

可见 SystemServer 的 main 函数, 主要做了入下操作

至此这个系统服务进程便启动完成了

总结

Zygote

从 ZygoteInit.main 中可以很清晰的看到 Zygote 进程的职责, 这里总结一下

SystemServer

从 SystemServer 对象的 run 方法中可以很清晰的了解到它启动时的工作

上一篇 下一篇

猜你喜欢

热点阅读