提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


文章目录

  • 一、系统开机流程图
  • 二、Android开机各阶段
  • 1.BootLoader阶段(加载引导程序BootLoader到RAM中)
  • 2. kernel 阶段
  • 3. init 进程启动
  • 4. Zygote启动
  • 5. zygote启动SystemServer
  • 6. 启动桌面



一、系统开机流程图

Android 启动流程源码解析 android 启动过程_linux

二、Android开机各阶段

1.BootLoader阶段(加载引导程序BootLoader到RAM中)

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

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将会运行

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,所以启动函数在开机过程中只会执行一次。

4. Zygote启动

zygote虚拟机启动一个子进程system_server,同时定义了一个Socket用来处理AMS启动应用的请求

5. zygote启动SystemServer

ZygoteInit.java里面通过startSystemServer() fork出了SystemServer进程,SystemServer和Zygote进程是Android框架中两个重要的进程,系统里重要的进程都在SystemServer里开启,如AMS、WMS、PMS等。

6. 启动桌面

SystemServer启动后会初始化ActivityManagerService,同时加载本地系统服务库,调用createSystemContext()创建系统上下文,创建ActivityThread及各种服务

AMS开启后会调用finishRooting()完成系统引导过程,同时发送开机广播,ActivityManagerService会与zygote的Socket通信,请求启动Home。zygote收到AMS的连接请求后,zygote处理请求会通过fork启动新的应用进程,并最终启动Home。完成系统界面的加载与显示。