美文网首页
Android系统开机流程

Android系统开机流程

作者: 课本里的小明 | 来源:发表于2021-03-29 16:02 被阅读0次

    1.系统开机流程图

    系统流程图.PNG

    2 Android开机各阶段

    2.1 BootLoader阶段

    Android 设备上电后,首先会从处理器到Rom 的启动引导代码开始执行,Rom 会找 Boot loader 的代码,并加载到内存中。这一步由“新品厂商”负责设计和实现的。

    2.2 kernel 阶段

    Linux 内核开始启动,初始化各种软硬件环境、加载驱动程序、挂载根文件系统、并执行 init 程序,由此开启 Android 的世界。
    内核启动的执行的第一条的代码在head.S文件中,主要功能是实现压缩内核的解压和跳转到内核vmlinux内核的入口,kernel的C启动阶段可以理解为真正的启动阶段,从head.S看到,最终调用的是kernel/init/main.c的start_kernel()函数
    1)start_kernel()函数中执行了大量的初始化操作:
    2)setup_arch():主要做一些板级初始化,cpu初始化,tag参数解析,u-boot传递的cmdline解析,建立mmu工作页表,初始化内存布局,调用mmap_io建立GPIO、IRQ、MEMCTRL、UART,及其他外设的静态映射表,对时钟,定时器,uart进行初始化
    3)sched_init():初始化每个处理器的可运行队列,设置系统初始化进程即0号进程
    4)softirq_init():内核的软中断机制初始化函数
    5)console_init():初始化系统的控制台结构
    6)rest_init():调用kernel_thread()创建1号内核线程,调用schedule()函数切换当前进程,在调用该函数之前,Linux系统中只有两个进程,即0号进程init_task和1号进程kernel_init,其中kernel_init进程也是刚刚被创建的。调用该函数后,1号进程kernel_init将会运行

    2.3 init 进程启动

    init 进程时Linux 内核启动后创建的第一个用户空间进程 ,init在初始化过程中会启动很多守护进程。init进程的入口是system\core\init\init.cpp里的main函数:

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

    在init.cpp中,加载system\core\rootdir\init.rc 配置文件,init.rc配置文件会进行加载很多配置,创建文件夹及文件,然后初始化一些Android 驱动器。各个极端的顺序是:
    on early-init --> on init --> on late-init --> on early-fs --> on post-fs --> on late-fs --> on post-fs-data(在这个时候才开始 mkdir data) --> on zygote-start --> on boot
    在boot阶段会启动下面两个模块的服务

    on boot
         ........
         class_start core 
         class_start hal
         .......
    

    在android\system\core\init\builtin.c
    而start_class core 具体 对应了 int do_class_start(int nargs, char **args) 方法

     int do_class_start(int nargs, char **args)
     {
        /* Starting a class does not start services
         * which are explicitly disabled.  They must
         * be started individually.
         */
        service_for_each_class(args[1], service_start_if_not_disabled);
        return 0;
    
     }
    

    在android\system\core\init\init_parse.c中:

    void service_for_each_class(const char *classname,
                            void (*func)(struct service *svc))
    {
        struct listnode *node;
        struct service *svc;
        list_for_each(node, &service_list) {
            svc = node_to_item(node, struct service, slist);
            if (!strcmp(svc->classname, classname)) {
                func(svc);
            }
        }
    }
    

    其中 service_start_if_not_disabled 定义在builtin.c

    static void service_start_if_not_disabled(struct service *svc)
    {
        if (!(svc->flags & SVC_DISABLED)) {
            service_start(svc, NULL);
        } else {
            svc->flags |= SVC_DISABLED_START;
        }
    }
    

    然后就走到了到service_start()。通过class_start 来启动相关的 service 。

    开机动画bootanim属于core服务,但他不是自启服务,需要由surfaceflinger服务将bootanim启动。
    surfaceflinger属于core服务,自启动服务,在init进程的on boot阶段会启动surfaceflinger,surfaceflinger最后会启动StartPropertySetThread从而启动bootanim。
    surfaceflinger服务的main函数入口在main_surfaceflinger,主要有:
    1.启动Hidl服务,主要是DisplayService
    2.启动线程池
    3.初始化surfaceFlinger
    4.将SurfaceFlinger和GpuService注册到ServiceManager
    5.启动SurfaceFlinger线程
    具体实现在frameworks/native/services/surfaceflinger/
    surfaceflinger继承了Thread,执行run 方法后,本质上是调用c++ 中的pthread类,线程入口函数是ThreadLoop,ThreadLoop的含义是通过一个循环不断的调用该函数,当threadLoop返回 false的时候退出循环。
    由于bootanim的threadLoop返回false,所以启动函数在开机过程中只会执行一次。

    2.4 Zygote启动

    在init 执行过程中,在on boot阶段,会 trigger zygote-start,on zygote-start 会根据当前的加密状态选择启动服务,在init.rc中,import zygote 的启动rc文件。
    Zygote会执行一个app_process64可执行文件,这个文件调用的代码位于/frameworks/base/cmds/app_process/路径下,有一个文件app_main.cpp,入口是main 函数

    相关文章

      网友评论

          本文标题:Android系统开机流程

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