美文网首页
失眠必读系列——Android系统启动流程

失眠必读系列——Android系统启动流程

作者: _Jun | 来源:发表于2022-09-26 14:03 被阅读0次

    系统启动流程大致分以下五步:

    • Loader(加载引导程序Boot Loader)
    • Kernel(Linux内核层)
    • Native(init进程)
    • Framework(Zygote进程/SystemServer进程)
    • Application(应用层/Launcher进程)

    源码阅读地址参考(Android10):
    www.androidos.net.cn/android/10.…


    Loader

    从ROM中加载BootLoader到RAM(这一步由芯片公司执行)
    BootLoader:启动Android系统之前的引导程序,检测RAM,初始化硬件参数

    Kernel

    内核层,启动第一个进程:Swapper进程(pid=0),又称idle进程,用于初始化进程管理、内存管理、加载显示、相机、Binder等驱动

    启动kthreadd进程(pid=2),是linux系统的内核进程,是所有内核进程的鼻祖,会创建内核工作线程,内核守护进程等

    Kernel设置完成后,开始启动init进程

    Native

    启动init进程(pid=1),是Linux系统的用户进程,是所有用户进程的鼻祖,fork出一些用户守护进程,启动servicemanager,开机动画等(后续会详细介绍次阶段)

    init进程fork出Zygote进程(解析init.rc文件来启动Zygote进程),Zygote是第一个虚拟机进程,创建虚拟机,注册JNI函数等

    init进程fork出MediaServer进程,负责启动和管理整个C++ framework,包含AudioFlinger,CameraService等服务

    Framework

    Zygote进程启动后,加载ZygoteInit.java类,注册ZygoteScoket,加载虚拟机,加载类,加载系统资源,fork SystemServer进程,SystemServer是Zygote进程孵化的第一个进程,负责启动和管理整个Java framework

    Application

    SystemServer进程会启动Launcher进程,即桌面App


    Native层

    我们从Native层启动init进程开始 /system/core/init/main.cpp
    init进程启动 从system/core/init/main.cpp的main函数开始

    int main(int argc, char** argv) {
        ……
        if (argc > 1) {
           ……
            if (!strcmp(argv[1], "selinux_setup")) {
                return SetupSelinux(argv);
            }
            if (!strcmp(argv[1], "second_stage")) {
                return SecondStageMain(argc, argv);
            }
        }
        return FirstStageMain(argc, argv);
    }
    

    /system/core/init/first_stage_init.cpp
    先执行FirstStageMain
    /system/core/init/selinux.cpp
    再执行SetupSelinux
    /system/core/init/init.cpp
    最后执行SecondStageMain
    在SecondStageMain中执行了LoadBootScripts,在LoadBootScripts中可以看到,解析了init.rc文件

    int SecondStageMain(int argc, char** argv) {
        ……
        LoadBootScripts(am, sm);
        ……
    }
    
    static void LoadBootScripts(……) {
        ……
        if (bootscript.empty()) {
            parser.ParseConfig("/init.rc");
            ……
        }
        ……
    }
    

    /system/core/rootdir/init.rc

    ……
    import /init.${ro.zygote}.rc
    ……
    //解析时启动了ServiceManager
    start servicemanager
    ……
    start zygote
    start zygote_secondary
    ……
    

    /frameworks/native/cmds/servicemanager/servicemanager.rc

    service servicemanager /system/bin/servicemanager
    ......
    

    以服务的形式启动一个名为“servicemanager”的进程,执行路为/system/bin/servicemanager
    对应的源文件为service_manager.c 找到这个类中的入口函数 main 函数.(这里暂时不做介绍,后续会有专门的失眠系列来介绍servicemanager如何启动)


    终于到了比较熟悉的环节,我们以init.zygote64_32.rc为例 /system/core/rootdir/init.zygote64_32.rc

    service zygote  /system/bin/app_process64 ……  —socket-name=zygote
    ......
    service zygote_secondary  /system/bin/app_process32 ……
    ......
    
    • init进程以服务的形式启动一个名为“zygote”的进程,执行路为/system/bin/app_process64

    • 创建名为zygote的socket,用于后续IPC

    • 创建了名为“zygote_secondary”的进程,用于适配不用的abi架构

    /frameworks/base/cmds/app_process64/app_main.cpp app_main.cpp中的main作为Zygote启动的入口

    int main(int argc, char* const argv[]){
        ......
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        ......
        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;
            }
        }
        ......
        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),调用start方法
    • 由于zygote=true,调用runtime.start,执行ZygoteInit文件

    /frameworks/base/core/jni/AndroidRuntime.cpp

    void AndroidRuntime::start(){
        ……
        if (startVm(&mJavaVM, &env, zygote) != 0) {
            return;
        }
        onVmCreated(env);
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
        ……
    }
    
    int AndroidRuntime::startReg(JNIEnv* env){
        ……   
        if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
            env->PopLocalFrame(NULL);
            return -1;
        }
        ……
        return 0;
    }
    
    void AndroidRuntime::onVmCreated(){}
    
    static const RegJNIRec gRegJNI[] = {
        REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
        ……
    }
    
    • startVm启动虚拟机
    • 执行onVmCreated方法,空方法
    • 执行startReg方法
    • 执行register_jni_procs方法,注册JNI函数
    • 后续代码自行查看,反射调用Zygoteinit的main方法

    Framework层

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

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        ……
        //预加载资源
        preload(bootTimingsTraceLog);
        ……
        final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
        zygoteServer = new ZygoteServer(isPrimaryZygote);
        ……
        //fork systemserver进程
        if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) {
                    r.run();
                    return;
                }
        }
        ……
        caller = zygoteServer.runSelectLoop(abiList);
        ……
    }
    

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

    ZygoteServer(boolean isPrimaryZygote) {
        ……
        if (isPrimaryZygote) {
        mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
        ……
        }
        ……
    }
    

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

    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        ……
        FileDescriptor fd = new FileDescriptor();
        fd.setInt$(fileDesc);
        return new LocalServerSocket(fd);
        ……
    }
    
    • 预加载资源(反射加载类,加载资源drawable / color资源, 即com.android.internal.R.xxx开头的资源)
    • 创建ZygoteServer对象,注册socket,zygote作为服务端, 不断接受其他进程发来的消息
    • fork System Server(验证了System Server是Zygote进程孵化的第一个进程)
    • 执行zygoteServer.runSelectLoop(abiList);无限循环等待AMS请求,代码如下: frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    Runnable runSelectLoop(String abiList) {
        while(true){
        ……
        final Runnable command = connection.processOneCommand(this);
        ……
        }
    }
    

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

    Runnable processOneCommand(ZygoteServer zygoteServer) {
        ……
        args = Zygote.readArgumentList(mSocketReader);
        ……
        pid = Zygote.forkAndSpecialize(……);
        ……
    }
    

    通过socket,客户端connect,服务端accept,客户端write,服务端read,根据args中的各种参数,执行Zygote.forkAndSpecialize,即Zygote孵化子进程


    启动 System Server

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

    private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {
        ……
        /* Request to fork the system server process */
        pid = Zygote.forkSystemServer(……)
        ……
        //创建成果,会返回父进程pid=0
        if (pid == 0) {
            ……
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
    }
    

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

    public static int forkSystemServer() {
        ……
        int pid = nativeForkSystemServer();
        ……
    }
    

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

    private static Runnable handleSystemServerProcess() {
        //先是创建了classloader cl,一路传下去
        ……
        return ZygoteInit.zygoteInit(……,cl);
    }
    
    public static final Runnable zygoteInit(cl) {
        ……
        return RuntimeInit.applicationInit(cl);
    }
    

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

    protected static Runnable applicationInit() {
        ……
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }
    
    protected static Runnable findStaticMain(……) {
        //这里通过传来的cl,加载类,通过类找到方法(自行查看)
        ……
        return new MethodAndArgsCaller(m, argv);
    }
    
    static class MethodAndArgsCaller implements Runnable {
        ……
        public void run() {
            //这里反射执行该方法,即SystemServer的main方法
            mMethod.invoke(null, new Object[] { mArgs });
        }
    }
    

    fork SystemServer进程完成后,执行handleSystemServerProcess,一路跟踪下来,返回一个runnable,内部执行方法的调用,即通过反射机制执行SystemServer类的main函数

    frameworks/base/services/java/com/android/server/SystemServer.java

    public static void main(String[] args) {
        new SystemServer().run();
    }
    
    private void run() {
        ……
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        ……
    }
    

    SystemServer.run中执行各种服务的初始化,其中startOtherServices中启动了launcher,即桌面app(这里暂时不做过多介绍,后续会有专门的失眠系列来介绍SystemServer如何启动,以及做了什么)


    结尾:

    失眠必读系列未完待续,有任何错误,虚心讨教,欢迎指正...

    • Android 系统启动流程
    • Service Manager 启动流程
    • System Server 启动流程
    • AMS 如何注册
    • Binder 源码阅读
    • Activity 启动流程
    • ......

    参考资料:

    www.androidos.net.cn/android/10.… www.jianshu.com/p/3a728f7f8… blog.csdn.net/Heisenberg_…

    作者:CoolStew
    链接:https://juejin.cn/post/7146403757570392101

    相关文章

      网友评论

          本文标题:失眠必读系列——Android系统启动流程

          本文链接:https://www.haomeiwen.com/subject/jxtxartx.html