基于Android13的系统启动流程分析(五)之Zygote和SystemServer启动流程

zygote和SystemServer的创建都在SecondStageMain阶段之后,到此阶段可以使用adb功能是可以正常使用了

一. Android系统启动流程

  1. 基于Android13的系统启动流程分析(一)之SeLinux权限介绍
  2. 基于Android13的系统启动流程分析(三)之FirstStageMain阶段
  3. 基于Android13的系统启动流程分析(四)之SecondStageMain阶段
  4. 基于SecondStageMain阶段解析rc文件后会启动zygote进程
  5. zygote进程启动过后会通过JNI方式回调到上层再调回到底层的fork函数创建出SystemServer

二. Zygote服务创建源码分析

在init.rc文件中会执行class_start main来启动zygote,代码如下

# 启动zygote
on nonencrypted
    class_start main
    class_start late_start

这个main就是zygote,可以通过init.{zygote64}.rc来查看,代码如下

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    # class : 给服务指定一个类属
    class main
    priority -20
    # user 在执行此服务之前先切换用户名。当前默认为root.
    user root
    # 切换组名
    group root readproc reserved_disk
    # 在/dev/socket/下创建一个socket,并传递创建的文件描述符fd给服务进程
    # 其中type必须为dgram或stream,seqpacket.用户名和组名默认为0
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks
    # oneshot : 当此服务退出时不会自动重启.
    # disabled:服务不会自动运行,必须显式地通过服务器来启动
    # 据设备相关的关键服务,如果在4分钟内,此服务重复启动了4次,那么设备将会重启进入还原模式。
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

第二个参数就是服务进程的名称,通过class指定函数入口,并且位于:/system/bin/app_process64,可以看到audioservercameraservermedianetdwificond这些进程都隶属于zygote进程中,那就代表着

  • 如果zygote挂了,这些进程将一起died
  • 如果这些进程挂了,并不会影响zygote died

如果zygote挂了将会捕获到进程异常信号,将zygote进程进行重启,zygote main入口位置:
frameworks/base/cmds/app_process/app_main.cpp

1. app_main.cpp源码分析

int main(int argc, char* const argv[])
{
    ...
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...

    // 如果zygote为true则代表即将创建该进程
    // 如果startSystemServer为true则代表创建zygote时也会创建SystemServer
    // 系统正常启动都会将这两个bool默认给到true
    // 因为rc启动main后携带了--zygote和--start-system-server两个参数
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {// zygote将为true,名称就叫:zygote
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {// startSystemServer将为true
            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()) {
       ...
    } else {
        // 进入创建zygote模式
        // 创建/data/dalvik-cache,为后续会创建Dalvik虚拟机做准备
        maybeCreateDalvikCache();

        // 如果startSystemServer为true的话(默认为true)
        // 将”start-system-server”放入启动的参数args
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        ...
        // 将所有剩余参数传递给args,例如application或tool或start-system-server或abi
        // 这些启动参数将会传递到其他进程中,后续取出参数决定是否启动systemServer等操作
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
    ...

    // zygote为真,将创建zygote,该args启动参数会包含start-system-server
    // 调用runtime(AppRuntime)的start来启动zygote,将args传入,因为args包含了启动SystemServer的标志
    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.");
    }
}

以上代码就是启动zygote和将start-system-server放入启动参数,后续会读取参数启动SystemServer,继续分析一下runtime.start的com.android.internal.os.ZygoteInit"进程,位于:frameworks/base/core/jni/AndroidRuntime.cpp

2. AndroidRuntime.cpp源码分析

Vector<String8>& options就是包含了start-system-server的启动参数,通过app_main传递过来的

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());
    // 默认会启动SystemServer
    static const String8 startSystemServer("start-system-server");
    // 是否私有,如果SystemServer会被创建时,将会设置为私有
    bool primary_zygote = false;

    for (size_t i = 0; i < options.size(); ++i) {
        // options就是传递过来的args,默认是包含了start-system-server
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           ...
        }
    }

    // 获取环境变量,这里第一次执行时默认为空,所以rootDir不存在
    // = 将直接拿到/system作为rootDir并设置环境变量
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /system does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }
	...

    /* start the virtual machine */
    // 这里就开始启动虚拟机了
    // JNI功能初始化
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // 创建Dalvik虚拟机(这里-->DVM==JavaVM)
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 调用startReg函数用来为DVM注册JNI
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
	// 通过反射拿到String类型
    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    //options就是app_main.cpp传递过来的args,包含了start-system-server
    // 将options转换为array list对象
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    //从app_main的main函数得知className为com.android.internal.os.ZygoteInit
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    // 将数据转换给java类型的array 数组
    env->SetObjectArrayElement(strArray, 0, classNameStr);

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

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
     // 启动com.android.internal.os.ZygoteInit,该线程成为JVM的主进程,在VM退出之前不会返回
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
       ...
    } else {
        // 通过反射的方式,找到ZygoteInit的main函数
        // 若获取到内容则执行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 {
            // 通过JNI调用ZygoteInit的main函数,将args(strArray)传递到java层
            // 因为ZygoteInit的main函数是Java编写的,因此需要通过JNI调用
            // 所以这里继续跟到java层面:ZygoteInit.java
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
			...
        }
    }
    // 若执行到这里,则会结束zygote创建,关闭jvm
    free(slashClassName);
    ALOGD("Shutting down VM\n");
    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");
}

可以看到以上的代码主要就是初始化了JNI(c++与Java交互)功能并创建并启动了JVM虚拟机,通过反射的方式去启动ZygoteInit.java的main方法,并将args参数(包含了是否启动SystemServer的参数)传递过去。
而JVM虚拟机进程就是:com.android.internal.os.ZygoteInit,而ZygoteInit进程位于:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

3. ZygoteInit.java源码分析

 public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
        // 标记zygote开始了
        ZygoteHooks.startZygoteNoThreadCreation();
        // 设置zygote自己的用户组pid
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        Runnable caller;
        try {
           // 读取系统是否已经启动完成
            final long startTime = SystemClock.elapsedRealtime();
            final boolean isRuntimeRestarted = "1".equals(
                    SystemProperties.get("sys.boot_completed"));

            // 将行为写入trace log 标记目前正处于ZygoteInit阶段
            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.preForkInit();

            boolean startSystemServer = false;
            // zygote进程就是一个socket,名称就叫zygote
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                // 从AndroidRuntime.cpp中传递上来,已经包含了start-system-server
                // 所以startSystemServer = true
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } ...
            }
            // 为true,是私有zygote
            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            ...
            // 记录的trace log,只记录到这个地方
            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // 初始化socket,从环境中获取套接字FD(ANDROID_SOCKET_zygote)
            // 若获取不到则创建一个用于和systemServer通信的socket,当systemServer fork出来后socket进程将关闭
            Zygote.initNativeState(isPrimaryZygote);
          	...

            // 根据环境变量(LocalServerSocket)获取zygote文件描述符并重新创建一个socket,可以从这里看到zygote其实就是一个socket
            // 这个name为”zygote”的Socket用来等待ActivityManagerService来请求Zygote来fork出新的应用程序进程
            // 所以ActivityManagerService里启动应用程序(APP),都是由该zygote socket进行处理并fork出的子进程
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            // 默认为true,将启动systemServer
            if (startSystemServer) {
                // zygote就是一个孵化器,所以这里直接fork(分叉,派生)出来SystemServer
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
				...
				// 让SystemServer子进程运行起来
                if (r != null) {
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // 让zygote socket(注意不是systemServer zygote)循环运行
            // 等待client进程来请求调用,请求创建子进程(fork出子进程(例如等待AMS的请求))
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
           ...
        } finally {
            if (zygoteServer != null) {
                // 停止关于systemServer的socket,保留和AMS通信的socket
                // 在initNativeState阶段创建了一个和systemServer通信的socket
                // 接着拿到systemServer socket文件描述符重新创建了一个可以和AMS通信的socket(/dev/socket/zygote)
                zygoteServer.closeServerSocket();
            }
        }
        ...
    }
  • 以上代码讲述了SystemServer socket的创建,将行为写入到trace log日志系统中,并通过JNI调用到底层的fork函数,孵化出SystemServer进程,如果SystemServer创建成功并已经运行了就会将当前socket进行close
  • 期间会创建一个zygote socket,用于等待其他子进程来连接,例如等待AMS(activity manager service)来连接该socket,然后继续fork出子进程(也就是应用程序,所以应用程序就是通过zygote来fork出来的)
  • 创建了2个socket,一个是systemServer socket(Zygote.initNativeState(isPrimaryZygote)来创建),一个是zygote socket(new ZygoteServer来创建),注意区分

继续来看一下zygoteServer = new ZygoteServer(isPrimaryZygote);

3.1 ZygoteInit.java#ZygoteServer(zygote socket)分析
 ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

        // 创建socket,名称为zygote,路径:/dev/sockets/zygote
        if (isPrimaryZygote) {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
           ...
        }
        ...
    }
    
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        //文件描述符通过ANDROID_socket_环境变量共享
        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("Socket unset or invalid: " + fullSocketName, ex);
        }

        try {
        	// 生成文件描述符
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            return new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }
    
public LocalServerSocket(FileDescriptor fd) throws IOException
    {
        // 创建socket并持续监听(等待client来调用)
        impl = new LocalSocketImpl(fd);
        impl.listen(LISTEN_BACKLOG);
        localAddress = impl.getSockAddress();
    }

简单点来说就是创建了一个zygoye socket ,位于/dev/sockets/zygote,并调用了runSelectLoop让其循环运行,等待新进程发来的请求并进行连接zygoteServer.runSelectLoop(abiList)然后fork出子应用程序进程

 Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        ArrayList<ZygoteConnection> peers = new ArrayList<>();

        // 拿到socket的文件描述符
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        ...
        while (true) {
            ...
            if (pollReturnValue == 0) {
            ...
            } else {
                boolean usapPoolFDRead = false;

                while (--pollIndex >= 0) {
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }

                    if (pollIndex == 0) {
                        // Zygote server socket
                        // acceptCommandPeer函数得到ZygoteConnection类并添加到Socket连接列表peers中,
                        // 接着将该ZygoteConnection的文件描述符添加到fd列表fds中,以便可以接收到ActivityManagerService发送过来的请求
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        socketFDs.add(newPeer.getFileDescriptor());
                    } 
               ...
            }
        }
    }

zygoteServer.runSelectLoop(abiList)持续等待进程来请求连接并fork出应用。

至此zygote socket已经启动完毕了,该socket会等待AMS进程发来的应用程序进程fork

继续看看systemServer是怎么被fork出来的
forkSystemServer(abiList, zygoteSocketName, zygoteServer);

3.2 ZygoteInit.java#forkSystemServer分析
 private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
        // 创建args数组,这个数组用来保存启动SystemServer的启动参数,其中可以看出SystemServer进程的用户id和用户组id被设置为1000;
        // 并且拥有用户组10011010,1018、1021、1032、30013010的权限;进程名为system_server;
        // 启动的类名为com.android.server.SystemServer
        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,3011,3012",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs;

        int pid;
        try {
            ...
            // 通过JNI形式去调用init进程下的fork函数,派生出systemServer进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        // pid == 0代表已经运行在子进程(SystemServer)上了
        // 代表SystemServer创建成功,创建成功后会关闭该socket
        if (pid == 0) {
            ...
            // 销毁zygoteServer,保留和AMS通信的socket(runSelectLoop)
            // 当SystemServer创建过后,zygoteServerSocket就没有用处了,进行关闭
            zygoteServer.closeServerSocket();
            // 处理 system server 进程初始化工作并启动SystemServer进程
            // 并启动了一个 binder 线程池供system server 进程和其他进程通信使用
            // 最后调用 RuntimeInit.applicationInit() 执行进程启动自身初始化工作
            // applicationInit()最后是通过反射调用了 SystemServer.java 中的 main() 方法
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

Zygote.forkSystemServer就是调用了底层的fork函数,不再进一步分析了。以上代码已知SystemServer子进程已经创建成功,将调用handleSystemServerProcess来启动SystemServer.java的入口
handleSystemServerProcess会一直调用到RuntimeInit.java#findStaticMain方法中

    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            // className:com.android.server.SystemServer
            // 反射拿到SystemServer类
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
           ...
        }

        Method m;
        try {
            // 反射拿到SystemServer.java的main函数,并启动
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
           ...
        } catch (SecurityException ex) {
           ...
        }
		...
        return new MethodAndArgsCaller(m, argv);
    }

可以看到handleSystemServerProcess下面的子方法去调用了com.android.server.SystemServer的main方法,至此SystemServer就创建和启动完毕了

至此SystemServer 已经创建并启动完毕了,那么SystemServer socket就会销毁并关闭

三. 总结

可以知道zygote是从rc中启动的,zygote本质上就是一个socket,不会关闭和销毁,而创建zygote时携带的StartSystemServer参数(必须携带此参数),会启动SystemServer子进程,SystemServer也是通过fork出来的,而底层和上层的交互是通过JNI实现的,SystemServer的启动是由zygoteInit通过反射的方式启动SystemServer的main方法

zygote启动时创建了服务端socket,用于SystemServer的创建,当SystemServer创建完成后则会关闭连接,期间已经调用了runSelectLoop来循环等待AMS及其他进程来请求连接,从而fork出应用程序的socket
服务端 socket会在SystemServer进程创建完毕后就会关闭,已经没有用处了,等待AMS发来连接将采用runSelectLoop方法进行循环等待

你可能感兴趣的:(Android开发旅途,zygote,android,adb,系统安全,aosp)