美文网首页
安卓手机启动时发生的那些事儿——中篇

安卓手机启动时发生的那些事儿——中篇

作者: 邱穆 | 来源:发表于2020-11-07 21:01 被阅读0次

    上篇文章我们谈到安卓手机启动时的前两部分,分别是BIOS和BootLoader阶段、Linux内核启动阶段,这篇文章,我们就来一起学习真正的进入安卓系统的启动流程。

    一、概览

    首先复习一下上篇所学,在安卓手机上,整个系统的启动可以分为三个过程,如下:

    • BIOS和BootLoader阶段
    • Linux内核启动
    • Android系统启动

    第一阶段主要由硬件和汇编语言完成,第二部分主要由C语言完成,第三部分主要由java完成。下面我们一起进入这第三部分的学习。

    二、Linux内核启动安卓系统

    上篇文章我们学到了运行Linux内核中的start_kernel(),然后start_kernel()函数最后通过调用kernel_thread()寻找init.rc文件,并启动init进程(pid = 1)。这一部分也就进行到了Native层,Linux 中的所有进程都是有init进程创建并运行的。Native层主要包括 init 进程以及其 fork 出来的用户空间的守护进程、 HAL 层、开机动画等。init进程是所有用户进程的鼻祖。其启动的主要内容如下:

    • Media Server(多媒体服务)、servicemanager(binder服务管家)、bootanim(开机动画)等重要服务;
    • installd(用于App安装)、ueventd、adbd、lmkd(用于内存管理)等用户守护进程;
    • Zygote进程,Zygote进程是Android系统的第一个Java进程,Zygote是所有Java进程的父进程,Zygote进程本身是由init进程孵化而来的。

    init进程的入口函数主要代码如下:

    /*位于安卓源码的system/core/init/init.cpp文件*/
    int main(int argc, char** argv) {
        if (!strcmp(basename(argv[0]), "ueventd")) {
            return ueventd_main(argc, argv);
        }
    
        if (!strcmp(basename(argv[0]), "watchdogd")) {
            return watchdogd_main(argc, argv);
        }
    
        if (REBOOT_BOOTLOADER_ON_PANIC) {
            install_reboot_signal_handlers();
        }
    
        add_environment("PATH", _PATH_DEFPATH);
    
        bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    
        if (is_first_stage) {
            boot_clock::time_point start_time = boot_clock::now();
    
            // 清理umask.
            umask(0);
    
            // 创建和挂载启动所需的文件目录
            mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
            mkdir("/dev/pts", 0755);
            mkdir("/dev/socket", 0755);
            mount("devpts", "/dev/pts", "devpts", 0, NULL);
            #define MAKE_STR(x) __STRING(x)
            mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
            chmod("/proc/cmdline", 0440);
            gid_t groups[] = { AID_READPROC };
            setgroups(arraysize(groups), groups);
            mount("sysfs", "/sys", "sysfs", 0, NULL);
            mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
            mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
            mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
            mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
            InitKernelLogging(argv);
            ······
        }
        //对属性服务进行初始化
        property_init();
        ······
       //创建epoll句柄
        epoll_fd = epoll_create1(EPOLL_CLOEXEC);
        if (epoll_fd == -1) {
            PLOG(ERROR) << "epoll_create1 failed";
            exit(1);
        }
        //用于设置子进程信号处理函数,如果子进程(Zygote)异常退出,init会根据调用该函数中设定的信号处理函数来处理
        signal_handler_init();
        //导入默认的环境变量
        property_load_boot_defaults();
        export_oem_lock_status();
        //启动属性服务
        start_property_service();
        set_usb_controller();
    
        const BuiltinFunctionMap function_map;
        Action::set_function_map(&function_map);
    
        Parser& parser = Parser::GetInstance();
        parser.AddSectionParser("service",std::make_unique<ServiceParser>());
        parser.AddSectionParser("on", std::make_unique<ActionParser>());
        parser.AddSectionParser("import", std::make_unique<ImportParser>());
        std::string bootscript = GetProperty("ro.boot.init_rc", "");
        if (bootscript.empty()) {
            //解析init.rc文件
            parser.ParseConfig("/init.rc");
            parser.set_is_system_etc_init_loaded(
                    parser.ParseConfig("/system/etc/init"));
            parser.set_is_vendor_etc_init_loaded(
                    parser.ParseConfig("/vendor/etc/init"));
            parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
        } else {
            parser.ParseConfig(bootscript);
            parser.set_is_system_etc_init_loaded(true);
            parser.set_is_vendor_etc_init_loaded(true);
            parser.set_is_odm_etc_init_loaded(true);
        }
    
        if (false) parser.DumpState();
    
        ActionManager& am = ActionManager::GetInstance();
        ······
    
        while (true) {
            int epoll_timeout_ms = -1;
            if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
                //内部遍历执行每个action中携带的command对应的执行函数
                am.ExecuteOneCommand();
            }
            if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
                //重启死去的进程
                restart_processes();
                if (process_needs_restart_at != 0) {
                    epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
                    if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
                }
    
                if (am.HasMoreCommands()) epoll_timeout_ms = 0;
            }
    
            epoll_event ev;
            int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
            if (nr == -1) {
                PLOG(ERROR) << "epoll_wait failed";
            } else if (nr == 1) {
                ((void (*)()) ev.data.ptr)();
            }
        }
    
        return 0;
    }
    

    init进程做的其中一件重要的事情就是解析init.rc文件,init.rc文件是由Android初始化语言(AIL)编写的脚本,主要用来启动各种服务,我们关注的Zygote进程就是由init.rc拆分后的init.zyygoteXX.rc定义的,以64位系统为例,就是init.zyygote64.rc文件。主要代码如下:

    /*位于system/core/rootdir/init.zygote64.rc*/
    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
        class main
        priority -20
        user root
        group root readproc
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        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
    

    这段service的主要作用就是通知init进程创建名为zygote的进程,程序路径位于/system/bin/app_process64,后面是要传递的参数。class main指的是Zygote的classname为main。
    而在init.rc有如下配置代码:

    on nonencrypted
        class_start main
        class_start late_start
    

    其中class_start是一个COMMAND,对应的函数为do_class_start,而main就是Zygote的classname,因此class_start min是用来启动Zygote的,do_class_start函数在builtins.cpp定义,关键代码如下:

    static int do_class_start(const std::vector<std::string>& args) {
            /* Starting a class does not start services
             * which are explicitly disabled.  They must
             * be started individually.
             */
        ServiceManager::GetInstance().
            ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
        return 0;
    }
    

    而ForEachServiceInClass函数会遍历Service链表,找到classname为main的Zygote,并执行StartIfNotDisabled函数,该函数代码如下:

    bool Service::StartIfNotDisabled() {
        if (!(flags_ & SVC_DISABLED)) {
            return Start();
        } else {
            flags_ |= SVC_DISABLED_START;
        }
        return true;
    }
    

    可以看到,如果没有被对应的rc文件设置disable选项,则会调用Start()函数来启动该Service,因此我们来查看Start函数,主要代码如下:

    bool Service::Start() {
        // Starting a service removes it from the disabled or reset state and
        // immediately takes it out of the restarting state if it was in there.
        flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
    
        // 如果Service已经启动,则不启动
        if (flags_ & SVC_RUNNING) {
            return false;
        }
    
        bool needs_console = (flags_ & SVC_CONSOLE);
        if (needs_console) {
            if (console_.empty()) {
                console_ = default_console;
            }
    
            int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
            if (console_fd < 0) {
                PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
                flags_ |= SVC_DISABLED;
                return false;
            }
            close(console_fd);
        }
         //判断需要启动的Service对应的执行文件是否存在
        struct stat sb;
        if (stat(args_[0].c_str(), &sb) == -1) {
            PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
            flags_ |= SVC_DISABLED;
            return false;
        }
    ······
        pid_t pid = -1;
        if (namespace_flags_) {
            pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
        } else {
            pid = fork();
        }
        //当前代码在子进程进行
        if (pid == 0) {
            umask(077);
    ······
            //调用execve函数Service子进程就会被启动
            if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
                PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
            }
            _exit(127);
        }
    ······
        return true;
    }
    

    调用execve函数,Service子进程会被启动,并进入执行该Service的main函数,如果该Service是Zygote,则执行/system/bin/app_process64,对应app_main.cpp文件。其中的main函数代码如下:

    int main(int argc, char* const argv[])
    {
    ······
        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.");
        }
    }
    

    可知这个函数调用了runtime的start函数启动Zygote,至此Zygote就启动了。
    让我们总结下init进程的工作:

    • 创建和挂载启动所需要的文件目录
    • 初始化和启动属性服务
    • 解析init.rc并启动Zygote进程
      接下来,我们就即将进入真正的安卓系统启动过程。

    三、安卓系统启动

    3.1 概述

    在安卓系统中,DVM、和ART、应用程序进程以及运行系统的关键服务的SystemServer都是由Zygote进程来创建的,因此我们也称呼Zygote进程为受精卵进程或孵化器进程。下面我们就一起来学习Zygote进程启动过程。

    3.2 启动Java框架,即进入FrameWork层

    上一小节讲到,init启动Zygote是靠app_main.cpp的main函数中的runtime的start方法。我们就从这里继续分析学习。

    int main(int argc, char* const 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;
            } 
            ······
        }
    ······
        if (!niceName.isEmpty()) {
            runtime.setArgv0(niceName.string(), true /* setProcName */);
        }
    ······
        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进程都是通过fork自身来创建子进程,所以有必要检查当前运行在哪个进程当中。
    如果运行在Zygote进程,就会执行第三段代码,调用runtime的start函数。该函数的主要关键如下:

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
    ······
        /* 启动java虚拟机 */
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) {
            return;
        }
        onVmCreated(env);
    
        //为java虚拟机注册JNI方法
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
    ······
        //从app_main的main函数知道className为com.android.internal.os.ZygoteInit
        stringClass = env->FindClass("java/lang/String");
        assert(stringClass != NULL);
        strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
        assert(strArray != NULL);
        classNameStr = env->NewStringUTF(className);
        assert(classNameStr != NULL);
        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);
        }
    
        //将className的“.”替换为“/”
        char* slashClassName = toSlashClassName(className);
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        } else {
            //找到Zygote的main方法
            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方法
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
    
    #if 0
                if (env->ExceptionCheck())
                    threadExitUncaughtException(env);
    #endif
            }
        }
    ······
    }
    

    根据注释可以看到,这个函数的主要作用,就是启动Java虚拟机,并为其注册JNI方法,然后根据className找到ZygoteInit,顺利通过JNI调用其main函数。至于为什么要使用JNI,是因为ZygoteInit是由java语言编写的,当前的运行逻辑在Native中,需要进入FrameWork层,也就是java框架层。

    3.3 FrameWork层发生的事情

    Zygote成功进入Java框架层,换句话说就是Zygote开创了Java框架层。该main方法关键代码如下:

    public static void main(String argv[]) {
            try {
                //创建一个Server端的socket,socketName为“zygote”
                zygoteServer.registerServerSocket(socketName);
                if (!enableLazyPreload) {
                    bootTimingsTraceLog.traceBegin("ZygotePreload");
                    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                    //预加载类和资源
                    preload(bootTimingsTraceLog);
                    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                    bootTimingsTraceLog.traceEnd(); // ZygotePreload
                } else {
                    Zygote.resetNicePriority();
                }
    ······
                if (startSystemServer) {
                    //启动SystemServer进程
                    startSystemServer(abiList, socketName, zygoteServer);
                }
    
                Log.i(TAG, "Accepting command socket connections");
                //等待AMS请求
                zygoteServer.runSelectLoop(abiList);
                zygoteServer.closeServerSocket();
            } catch (Zygote.MethodAndArgsCaller caller) {
                caller.run();
            } catch (Throwable ex) {
                Log.e(TAG, "System zygote died with exception", ex);
                zygoteServer.closeServerSocket();
                throw ex;
            }
        }
    

    第一段代码创建了一个Server端的socket,socketName为“zygote”,这个socket用于等待AMS请求Zygote来创建新的应用程序进程,然后预加载类和资源,之后启动SystemServer进程,这样系统的服务也会由SystemServe进程启动起来,最后调用zygoteServer的runSelectLoop方法来等待AMS,可以总结ZygoteInit的main方法主要做了四件事:

    • 创建一个Server端的Socket
    • 预加载类和资源
    • 启动SystemServer进程
    • 等待AMS请求创建新的应用程序进程

    具体的这四个函数的详细细节,本处不在探讨,待下次再进行学习。这里只说一下SystemServer进程的工作:

    • 启动Binder线程池,这样就可以与其他进程通信
    • 创建SystemServiceManager,其用于对系统的服务进程创建、启动和生命周期管理
    • 启动各种系统服务

    四、总结

    这一次,我们学习了从kernel到framework层的工作,大致是梳理了安卓手机从按下电源键到启动安卓系统的过程,不过大家肯定还有疑问,这里并没有显示桌面,并没有启动软件,这些问题,我准备在下一篇文章再和大家一起学习。

    相关文章

      网友评论

          本文标题:安卓手机启动时发生的那些事儿——中篇

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