这篇是自己学习所用,请谨慎观看,具体内容可看下面博客:
Android启动流程简析
Android系统启动(里面含有所有函数和类的源码)

Android启动大纲概念图

安卓启动 Android 架构图 启动分析 init总结

Zygote进程在init进程中以service的方式启动的。通过init.rc中通过"import"的方式引入文件

zygote流程图

zygote是核心进程,支撑着所有android的应用程序。

  • 步骤1、系统加电,执行bootloader。 bootloader负责初始化软件运行所需的最小硬件环境,最后加
    载内核到内存中。
  • 步骤2、内核加载进内存后,将首先进入内核引导阶段,在引导阶段最后,调用start_kernel进入内
    核启动阶段。 start_kernel最终启动用户空间的init程序。
    -步骤3、 init程序负责解析配置文件,开启系统守护进程。两个最重要的守护进程是zygote和
    ServiceManager。前者是Android启动第一个Dalvik虚拟机,它将负责启动Java世界的进程;后者是
    Binder通信的基础。
    - 步骤4、 zygote虚拟机启动子进程system_server,在system_server中开启了Android核心系统服务,并将核心系统服务添加到ServiceManager,然后系统进入systemReady状态
  • 步骤5、在systemReady状态下,ActivityManagerService与zygote中的Socket通讯,通过zygote启动Home应用,进入系统桌面

Android 启动模式

  1. recovery 升级模式:启动recovery模式,内核和文件系统
  2. 正常启动模式:引导内核和启动Android系统


    启动模式

    recovery:清除数据和完成系统升级
    升级:差量包升级和全包升级(最好不要断电)

1、 bootloader介绍

可看博客bootloader
Bootloader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。

调用流程:
crt0.S > kmain > arch_init > target_init > apps_init > aboot_init

1.1、crt0.S

crt0.S代码大体如下,在_start中先主要完成CPU初始化,禁用mmu,禁用cache,初始化异常向量表等操作,最后将直接跳转到函数kmain中

2、 kernel 初始化介绍

Kernel初始化可以分成三部分:zImage解压缩、kernel的汇编启动阶段、Kernel的C启动阶段
内核启动引导地址由bootp.lds决定,内核启动的执行的第一条的代码在head.S文件中,主要功能是实现压缩内核的解压和跳转到内核vmlinux内核的入口,head.S是Linux内核启动的汇编程序入口,但head.S
中并没有直接调用start_kernel
在引导阶段最后,调用start_kernel进入内核启动阶段,start_kernel最终启动用户控件的init程序

3、 init程序

严格上讲,Android系统实际上是运行于Linux内核之上的一系列"服务进程",并不算一个完成意义上的"操作系统";而这一系列进程是维持Android设备正常工作的关键,所以它们肯定有一个"根进程",这个"根进程"衍生出了这一系列进程。这个"根进程"就是init进程。

学习目标:
  1. init进程是如何创建zygote的?zygote对应的service section
  2. property service来管理安卓系统的很多属性,这个属性服务是如何工作的.
    property_init初始化属性相关的资源。start_prperty_service()函数,启动属性服务

init程序负责解析init.rc配置文件来构建出系统的初始形态,开启系统守护进程。最重要的守护进程是zygote和servicemanager。前者是android启动的第一个dalvik虚拟机,负责启动java世界的进程。后者是binder通信的基础。

• 1、初始化文件系统和日志系统,为之后的执行阶段做准备。这部分主要是Linux标准函数的调用。
• 2、解析init.rc和init..rc初始化文件。
• 3、触发需要执行的Action和Service。
• 4、 init循环监听处理事件。 init触发所有Action后,进入一个无限循环,执行在可执行队列中的命令,
重启异常退出的Service,并循环处理来自propertyservice(属性服务)、 signal和keychord的事件。

3.1 init中第一个应用程序(pid=1)

内核起来后的第一个进程(命令ps可看进程)

init进程
ps:解析启动脚本是将服务、环境变量全部解析,然后根据脚本的设置来启动相关的服务、执行相关的命令,启动那个服务之后,就守护所有的服务。
init.cpp的入口函数是mian函数,同时也是ueventd和watchdogd守护进程的入口,通过参数进行控制.
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);    }}

主要是检查启动程序的文件名,这里面分成三种情况

1 如果文件名是"ueventd",则执行守护进程ueventd的主函数ueventd_main()
2 如果文件名是"watchdogd",则执行看门狗守护进程的主函数watchdogd_main()
如果文件名既不是"ueventd"也不是"watchdogd",则往下执行

3.2 init中创建目录,挂载分区

默认情况下,一个进程创建出来的文件和文件夹属性都是022,使用umask()函数能设置文件属性的掩码。参数为0意味着进程创建的文件属性是0777。接着创建一些基本的目录包括dev、proc、sys等,同时把分区mount到对应的目录
system/core/init/first_stage_init.cpp

// ****************** 第二部分 ****************** // 设置文件属性为0777    // Clear the umask.    umask(0);// ****************** 第三部分 ****************** // 设置环境变量地址    add_environment("PATH", _PATH_DEFPATH);// ****************** 第四部分 ****************** // 创建一些基本目录,包括/dev、/proc、/sysfc//把一些文件系统如"tmpfs",sysfs等mount到项目的目录中    //判断是否是第一次    bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);    // Get the basic filesystem setup we need put together in the initramdisk    // on / and then we'll let the rc file figure out the rest    //如果是第一次.    if (is_first_stage) {        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");        mkdir("/dev/pts", 0755);        mkdir("/dev/socket", 0755);        mount("devpts", "/dev/pts", "devpts", 0, NULL);        mount("proc", "/proc", "proc", 0, NULL);        mount("sysfs", "/sys", "sysfs", 0, NULL);    }// ****************** 第五部分 ****************** //调用open_devnull_stdio()函数把标准输入、标准输出和标准错误重定向到空设备文件"/dev/null",这是创建守护进程常用的手段    // We must have some place other than / to create the device nodes for    // kmsg and null, otherwise we won't be able to remount / read-only    // later on. Now that tmpfs is mounted on /dev, we can actually talk    // to the outside world.    open_devnull_stdio();// ****************** 第六部分 ****************** //调用klog_init()函数创建节点/dev/kmsg,这样init进程可以使用kernel的log系统来出log了,同时调用klog_set_level函数来设置输出log的级别。// 启动kernel log    klog_init();    klog_set_level(KLOG_NOTICE_LEVEL);    // 输出init启动阶段的log          NOTICE("init%s started!\n", is_first_stage ? "" : " second stage");

init进程会调用property_init创建一个共享区域来存储属性值,初始化完后获取kernel传过来的cmdline去设置一些属性,然后初始化SELinux和安全上下文。接着会通过property_load_boot_defaults去加载default.prop等文件初始化系统属性
init.cpp
具体实现在:property_service.cpp

// ****************** 第七部分 ****************** // 如果不是第一次,则进行一些设置,我又将这里具体划分为4个部分// 设置系统属性    if (!is_first_stage) {        // Indicate that booting is in progress to background fw loaders, etc.// 7.1 创建初始化标志        close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));//在/dev目录下创建一个空文件".booting"表示初始化正在进行//is_booting()函数会依靠空文件".booting"来判断是否进程处于初始化中,初始化结束后,这个文件会被删除//7.2 初始化Android的属性系统,property_init()函数主要作用是创建一个共享区域来存储属性值        property_init();        // If arguments are passed both on the command line and in DT,        // properties set in DT always have priority over the command-line ones.//7.3  解析(设备树)DT和命令行中的kernel启动参数        process_kernel_dt();        process_kernel_cmdline();        // Propogate the kernel variables to internal variables        // used by init as well as the current required properties.//7.4  设置系统属性,设置ro属性根据之前的ro.boot这类的属性值        export_kernel_boot_props();    }// ****************** 第八部分 ******************     // Set up SELinux, including loading the SELinux policy if we're in the kernel domain.    // 调用selinux_initialize函数启动SELinux//安全增强型 Linux(Security-Enhanced Linux)它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。    selinux_initialize(is_first_stage);    // If we're in the kernel domain, re-exec init to transition to the init domain now    // that the SELinux policy has been loaded.    if (is_first_stage) {        // 按照selinux policy要求,重新设置init文件属性        if (restorecon("/init") == -1) {            ERROR("restorecon failed: %s\n", strerror(errno));            security_failure();        }        char* path = argv[0];        // 设置参数  --second-stage        char* args[] = { path, const_cast("--second-stage"), nullptr };        // 执行init进程,重新进入main函数        if (execv(path, args) == -1) {            ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));            security_failure();        }    }    // These directories were necessarily created before initial policy load    // and therefore need their security context restored to the proper value.    // This must happen before /dev is populated by ueventd.    INFO("Running restorecon...\n");    restorecon("/dev");    restorecon("/dev/socket");    restorecon("/dev/__properties__");    restorecon_recursive("/sys");

// ******************init 第九部分 ******************

这部分分为上下按两个阶段
第一阶段主要是调用epoll_create1创建epoll句柄,如果创建失败,则退出。
第二阶段是调用signal_handler_init()函数,主要是装载进程信号处理器。
signal_handler_init()函数主要是当子进程被kill之后,会在父进程接受一个信号。处理这个信号的时候往sockpair一段写数据,而另一端的fd是加入epoll中
// 在Linux中,父进程是通过捕捉SIGCHILD信号来得知子进程运行结束的情况
这里我们简单介绍下信号:
Linux进程通过相互发送接收消息来实现进程间通信,这些消息被称为"信号"。每个进程在处理它进程发送的信号时,都要注册处理者,处理者被称为信号处理器。

每个进程在处理其他进程发送的signal信号时都需要先注册,当进程的运行状态改变或终止时会产生某种signal信号,init进程是所有用户空间进程的父进程,当其子进程终止时产生SIGCHLD信号,init进程调用信号安装函数sigaction(),传递参数给sigaction结构体,便完成信号处理的过程。
当init进程调用signal_handler_init后,一旦受到子进程终止带来的SIGCHLD消息后,将利用信号处理者SIGCHLD_handler向signal_write_fd写入信息;epoll句柄监听到signal_read_fd收到消息后,将调用handle_signal进行处理。如下图

image.png

    epoll_fd = epoll_create1(EPOLL_CLOEXEC);    if (epoll_fd == -1) {        ERROR("epoll_create1 failed: %s\n", strerror(errno));        exit(1);    }    signal_handler_init();{}

// ****************** 第十部分 ******************
上半部分是调用property_load_boot_defaults()函数解析根目录的default.prop的属性,设置默认属性配置的相关工作。下半部分是调用start_prperty_service()函数,启动属性服务,并接受属性的socket的fd加入到epoll中,也定义了处理函数。那我们依次来看下

property_load_boot_defaults();start_property_service();

// ****************** 第十一部分 ******************

// 重点部分,解析init.rc文件

init_parse_config_file("/init.rc");

// ****************** 第十二部分 ******************
将把Action加入执行队列中

// 执行init.rc中触发器为 on early-init的语句,即将early-init的Action添加到链表action_queue中

    action_for_each_trigger("early-init", action_add_queue_tail);    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...    // 等冷插拔设备初始化完成,即创建wait_for_coldboot_done Action并添加到action_queue和action_list中    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");    // ... so that we can start queuing up actions that require stuff from /dev.    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");    // 设备组合键的初始化操作,创建keychord_init Action 并添加到链表action_queue和action_list中     queue_builtin_action(keychord_init_action, "keychord_init");    // 创建console_init动作并添加到链表action_queue和action_list中    queue_builtin_action(console_init_action, "console_init");    // Trigger all the boot actions to get us started.    // 执行init.rc文件中触发器为 on init 的语句,将init动作添加到链表action_queue中    action_for_each_trigger("init", action_add_queue_tail);    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random    // wasn't ready immediately after wait_for_coldboot_done    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");    // Don't mount filesystems or start core system services in charger mode.    char bootmode[PROP_VALUE_MAX];    // 当处于充电模式,则charger加入执行队列;否则late-init加入队列。    if (property_get("ro.bootmode", bootmode) > 0 && strcmp(bootmode, "charger") == 0) {        action_for_each_trigger("charger", action_add_queue_tail);    } else {        action_for_each_trigger("late-init", action_add_queue_tail);    }    // Run all property triggers based on current state of the properties.    // 触发器为属性是否设置    queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");

上面大量的调用了action_for_each_trigger函数、action_add_queue_tai函数和queue_builtin_action.
action_for_each_trigger()
queue_builtin_action函数用来动态生成一个Action并插入到执行列表"action_queue中"。插入的Action由一个函数指针和一个表示名字的字符串组成。Android在以前版本中直接调用这些函数来完成某些初始化的工作,但是,这些函数可能会依赖init.rc里面定义的一些命令和服务的执行情况。现在把这些初始化函数也通过Action的形式插入到执行列表中,这样就能控制他们的执行顺序了。

****************** 第十三部分 ******************

        while (true) {        // 判断是否还有事件需要处理        if (!waiting_for_exec) {             //依次执行每个action中携带的command对应的执行函数            execute_one_command();             // 重启一些挂掉的进程            restart_processes();        }        // 决定timeout的时间,将影响while循环的间隔        int timeout = -1;       // 有进程需要重启是,等待进程重启        if (process_needs_restart) {            timeout = (process_needs_restart - gettime()) * 1000;            if (timeout < 0)                timeout = 0;        }        if (!action_queue_empty() || cur_action) {            timeout = 0;        }        // 进行性能数据采样        bootchart_sample(&timeout);        epoll_event ev;        // 没有事件来的话,最多阻塞timeout时间        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));        if (nr == -1) {            ERROR("epoll_wait failed: %s\n", strerror(errno));        } else if (nr == 1) {             // 根据上下文知道,epoll句柄(即epoll_fd)主要监听子进程结束,及其他进程设置系统属性的请求 ,根据事件的到来,执行对应处理函数            ((void (*)()) ev.data.ptr)();        }    }

最后init进程会进入到一个无线循环中去,在这个无线循环中,init进程会做以下五件事:

第一件事:调用函数execute_one_command来检查action_queue列表是否为空。如果不为空的话,那么init进程就将保存在列表头部中的action移除,并且执行这个被移除的action。由于前面我们将一个名称为"console_init"的action添加到action_queue列表中,因此,在这个无线循环中,这个action就会被执行,即console_init_action函数会被调用。

第二件事:调用函数restart_processes来检查系统中是否有进程需要重启。在启动脚本init.rc中,我们可以指定一个进程在退出之后会自动重启。在这种情况下,函数restart_processes就会检查是否存在需要重新启动的进程,如果存在的话,那么就将它重新启动起来。

第三件事:处理系统属性变化事件。当我们调用函数property_set来改变一个系统属性时,系统就会通过一个socket(通过调用函数get_property_set_fd可以获得它的文件描述符)来向init进程发送一个属性值改变事件通知。init进程接受到这个属性值改变事件之后,就会调用函数handle_property_set_fd来进行相应的处理。后面在分析第三个开机画面显示过程时,我们就会看到,SurfaceFlinger服务就是通过修改“ctl.start”和“ctl.stop”属性来启动和停止三个开机画面的。

第四件事:处理一种被称为"chorded keyboard"的键盘输入时间。这种类型为"chorded keyboard"的键盘设备通过不同的按键组合来描述不同的命令或者操作,它对应的设备为/dev/keychord。我们可以通过调用函数get_keychord_fd()来获的这个设备的文件描述符,以便可以监控它的输入事件,并且调用函数handle_keychord来对这些输入事件进行处理。

第五件事:回收僵尸进程。我们知道,在Linux内核中,如果父进程不等待子进程结束就退出,那么当子进程结束的时候,就会变成一个僵尸进程,从而占用系统的资源。为了回收这些僵尸进程,init进程会安装一个SIGCHLD信号接收器。当这些父进程已经退出了子进程退出的时候,内核就会发出一个SIGCHLD信号,给init进程,init进程就可以通过一个socket(通过调用函数get_signal_fd可以获得它的文件描述符)来将接受到的SIGCHLD信号读取回来,并且调用函数handle_signal来对接收到的SIGCHLD信号来进行处理,即回收哪些已经变成僵尸进程的子进程。

init源码分析

/proc:内核的信息输出目录。
selinux_klog_callback:这就是把信息写入klog中
在init.cpp中,main函数中,会创建很多的文件夹(如/dev),并且关在一些分区。
get_hardware_name中,
cat /proc/cpu可以显示,getprop ro.boot.hardware具体得到硬件信息。
cat /proc/cmdline:启动时传的参数

3.3 init.rc:启动脚本

init.rc文件是以“块”(section)为单位服务的,,一个“块”(section)可以包含多行。“块”(section)分成两大类:一类称为"动作(action)",另一类称为“服务(service)”.
无论是“动作(action)”块还是“服务(service)”块,并不是按照文件中的编码排序逐一执行的

  • 动作(action):以关键字"on" 开头,表示一堆命令
  • 服务(service):以关键字“service”开头,表示启动某个进程的方式和参数

一个init.rc脚本由4个类型的声明组成,即

Action——行为/动作
commands——命令/启动
services—— 服务
Options—— 选项
Action(动作)

on             ## 触发条件           ##执行命令         ##可以执行多个命令

init中在初始化属性和SELinux后,接着解析init.rc的文件内容,通过init.rc进行相关语法配置、启动进程以及启动的顺序

启动脚本
路径:/system/core/rootdir
image.png

parse_config()函数解析脚本文件的逻辑过程可以用一张流程图来表示,如下图所示。通过调用next_token()函数的作用就是寻找单词结束标志或行结束标志。 如果是单词结束符,就先存放在数组args中,如果找到的是行结束符,则根据行中的第一个单词来判断是否是一个"section","section"的标志有3个,关键字"on","service","import"。如果是"section"则调用函数parse_new_section来开启一个新"section"的处理,否则把这一行继续作为当前"section"所属的行来处理。

流程图

第一个函数:把启动脚本的命令解析到列表中,然后调用下面的函数


init 脚本

用parse_config来解析。
service_list:保存脚本中所有的服务
action_list:保存所有的操作
action_queue:把要执行的服务和操作保存在这里

命令和结构:lookup_keyword函数。
parse_new_section:把解析的加入到listaction。

init事件列表(list结构)

init事件列表

init事件结构

init事件结构
一个section下面挂着多个操作。

android 脚本执行和进程守护
启动脚本解析结果
解析后放入两个结构体中,然后放入队列中


都是on打头。
整理事件列表

init构建事件
将自己的函数放入到antion_queue中
service 事件分类

init进程执行命令和启动服务
const BuiltinFunctionMap function_map;Action::set_function_map(&function_map);//声明bai了一个类A,类A里声du明了一个成员函数void f(),但没有在类的zhi声明里给出f的定义,那么在类外定义f时,//就要写成void A::f(),表示这个f()函数是类A的成员函数ActionManager& am = ActionManager::GetInstance();ServiceManager& sm = ServiceManager::GetInstance();Parser& parser = Parser::GetInstance();parser.AddSectionParser("service", std::make_unique(&sm));//c++中的<>代表baiC++模板。parser.AddSectionParser("on", std::make_unique(&am));parser.AddSectionParser("import", std::make_unique(&parser));std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) {    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);}am.QueueEventTrigger("early-init");// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");// ... so that we can start queuing up actions that require stuff from /dev.am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");am.QueueBuiltinAction(keychord_init_action, "keychord_init");am.QueueBuiltinAction(console_init_action, "console_init");// Trigger all the boot actions to get us started.am.QueueEventTrigger("init");// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random// wasn't ready immediately after wait_for_coldboot_doneam.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");// Don't mount filesystems or start core system services in charger mode.std::string bootmode = GetProperty("ro.bootmode", "");if (bootmode == "charger") {    am.QueueEventTrigger("charger");} else {    am.QueueEventTrigger("late-init");}    // Run all property triggers based on current state of the properties.am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");

main函数最后会进入一个死循环,每次循环都会去调用ExecuteOneCommand执行命令列表中的一条命令,如果服务挂了还会调用restart_processes重启服务

while (true) {    // By default, sleep until something happens.    int epoll_timeout_ms = -1;    if (do_shutdown && !shutting_down) {        do_shutdown = false;        if (HandlePowerctlMessage(shutdown_command)) {            shutting_down = true;        }    }    if (!(waiting_for_prop || sm.IsWaitingForExec())) {        am.ExecuteOneCommand();    }    if (!(waiting_for_prop || sm.IsWaitingForExec())) {        if (!shutting_down) restart_processes();        // If there's a process that needs restarting, wake up in time for that.        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 there's more work to do, wake up again immediately.        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)();    }}

init进程初始化系统后,会化身为守护进程来处理子进程的死亡信号、修改属性的请求和组合键事件.
目的:了解init如何守护服务,设置property。
init在for循环中三个动作:

  1. 启动我们的服务,执行脚本命令
  2. 根据Shell或者系统中消息设置系统Prop
  3. 守护系统服务,如果服务退出,重启退出的服务
init与其他进程交互示意图

主要是两个套接字:

  1. 设置prop
  2. 监听子进程退出。


    init 处理prop消息分析

    函数:
    property_service_init_action。
    start_property_service
    property_set_fd
    handle_property_set_fd

init 守护服务分析
queue_builtin_action(signal_init_action,"signal_init")
sigchld_handler会创建两个socket,创建之后,init会监听signal_recv_fd,子进程会继承所有的,然后子进程意外退出时会触发sigchld,然后进行处理两个socket。(signla_fd发送给signal_recv_fd),然后用wait重启。
在init.rc中,import:导入其他的脚本
system/core/rootdir/init.rc, 在init.rc中,需要导入其他的脚本文件

import /init.environ.rcimport /init.usb.rcimport /init.${ro.hardware}.rcimport /vendor/etc/init/hw/init.${ro.hardware}.rcimport /init.usb.configfs.rcimport /init.${ro.zygote}.rc

on:


这四种方式,后面都会跟一些命令,在init.c中会解析on后面跟着的选项,后面的命令代表了执行的时间。
on trigger:条件判断是否执行。
在init.cpp中,启动init.rc各个阶段的顺序是early_init > init > late_init,在late_init中又会去触发其他阶段的启动,所以各个阶段在init中启动的顺序如下:
early_init > init > late_init > early-fs > fs > post-fs > late_fs > post-fs-data > zygote-start > early-boot > boot

在boot阶段会启动class为hal和core的服务

on boot    ...    class_start hal    class_start core

init.rc中支持的命令实现在builtins.cpp中,具体语法使用可以参考system/core/init/README.md

3.4 bootanim 启动

bootanim.rc定义了bootanim属于core服务,但是设置了disable说明bootanim不是自启动的服务,需要别的服务进行唤醒。

service bootanim /system/bin/bootanimation    class core animation    user graphics    group graphics audio    disabled    oneshot    writepid /dev/stune/top-app/tasks

kernel-vfs-bootUI-显示android 主lunch。

  1. init :守护进程
  2. surfaceflinger:界面管理服务,初始化显示,结束后调用startbootanim,启动bootanimation
  3. boot 启动界面服务,然后和surfaceflinger来进行交互,得到显示的层,根据显示机制,刷新屏幕
  4. zygote:用以创建所有的java应用程序和服务
  5. system_service:会在中间创建java层所有的服务

service.bootanim.exit为1时,退出bootanimation。

bootanim工作流程

3.5 surfaceflinger启动

代码里搜索bootanim,可以看到是surfaceflinger服务将bootanim启动,surfaceflinger属于core服务,自启动服务,在init进程的on boot阶段会启动surfaceflinger,surfaceflinger最后会启动StartPropertySetThread从而启动bootanim

service surfaceflinger /system/bin/surfaceflinger    class core animation    user system    group graphics drmrpc readproc    onrestart restart zygote    writepid /dev/stune/foreground/tasks    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0bool StartPropertySetThread::threadLoop() {    // Set property service.sf.present_timestamp, consumer need check its readiness    property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");    // Clear BootAnimation exit flag    property_set("service.bootanim.exit", "0");    // Start BootAnimation if not started    property_set("ctl.start", "bootanim");    // Exit immediately    return false;}

surfaceflinger服务的main函数入口在main_surfaceflinger,主要操作有:

启动Hidl服务,主要是DisplayService
启动线程池
初始化SurfaceFlinger
将SurfaceFlinger和GpuService注册到ServiceManager
启动SurfaceFlinger线程

int main(int, char**) {    startHidlServices();    signal(SIGPIPE, SIG_IGN);    // When SF is launched in its own process, limit the number of    // binder threads to 4.    ProcessState::self()->setThreadPoolMaxThreadCount(4);    // start the thread pool    sp ps(ProcessState::self());    ps->startThreadPool();    // instantiate surfaceflinger    sp flinger = new SurfaceFlinger();    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);    set_sched_policy(0, SP_FOREGROUND);    // Put most SurfaceFlinger threads in the system-background cpuset    // Keeps us from unnecessarily using big cores    // Do this after the binder thread pool init    if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);    // initialize before clients can connect    flinger->init();    // publish surface flinger    sp sm(defaultServiceManager());    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);    // publish GpuService    sp gpuservice = new GpuService();    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);    struct sched_param param = {0};    param.sched_priority = 2;    if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {        ALOGE("Couldn't set SCHED_FIFO");    }    // run surface flinger in this thread    flinger->run();    return 0;}

surfaceflinger继承了Thread(class Rectangle: public Shape),执行run方法后,本质上是调用c++中的pthread类,线程入口函数是threadLoop,threadLoop的含义是通过一个循环不断的调用该函数,当threadLoop返回false的时候退出循环

由于bootanim的threadLoop返回false,所以启动函数在开机过程中只会执行一次

4、Zygote启动

zygote本身是一个native的应用程序,由init进程根据init.rc文件中的配置项创建的。Zygote初始化时会创建创建虚拟机,同时把需要的系统类库和资源文件加载到内存里面。Zygote fork出子进程后,这个子进程也继承了能正常工作的虚拟机和各类系统资源,接下来子进程只需要装载APK文件的字节码文件就可以运行了。这样应用程序的启动时间就会大大缩短。

4.1 在init.rc脚本中配置

Zygote进程在init进程中以service的方式启动的。 通过init.rc中通过"import"的方式引入文件
当init进程真的启动zygote服务的时候,会走到会走到service_start()函数,
Android系统启动——4 zyogte进程 中详细讲解了service_start函数。

import /init.${ro.zygote}.rc

在init.rc执行过程中,在on boot阶段,会trigger zygote-start,on zygote-start会根据当前的加密状态选择启动服务。

import /init.${ro.zygote}.rc`on zygote-start && property:ro.crypto.state=unencrypted    exec_start update_verifier_nonencrypted    start netd    start zygote    start zygote_secondary

在init.rc中,import zygote的启动rc文件:import /init.${ro.zygote}.rc
主要是根据属性ro.zygote决定,rc文件位于alps/system/core/rootdir/:
init.zygote32.rc
init.zygote32_64.rc
init.zygote64.rc
init.zygote64_32.rc

4.2 app_main

主要功能由appruntime中的start来实现。
app_main 代码:/frameworks/base/cmds/app_process/app_main.cpp,:

int main(int argc, char* const argv[]){    // ******************** 第一部分 *********************    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return        // EINVAL. Don't die on such kernels.        if (errno != EINVAL) {            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));            return 12;        }    }    // ******************** 第二部分 *********************这部分主要是创建了AppRuntime对象,AppRuntime类继承自AndroidRuntime。接着从命令行参数中找到虚拟机相关的参数,添加到runtime对象    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));    // Process command line arguments    // ignore argv[0]    argc--;    argv++;     // ******************** 第三部分 *********************      int i;    for (i = 0; i < argc; i++) {        if (argv[i][0] != '-') {            break;        }        if (argv[i][1] == '-' && argv[i][2] == 0) {            ++i; // Skip --.            break;        }        runtime.addOption(strdup(argv[i]));    }    // Parse runtime arguments.  Stop at first unrecognized option.    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;            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;        }    }     // ******************** 第五部分 *********************      Vector args;    if (!className.isEmpty()) {        // We're not in zygote mode, the only argument we need to pass        // to RuntimeInit is the application argument.        //        // The Remainder of args get passed to startup class main(). Make        // copies of them before we overwrite them with the process name.        args.add(application ? String8("application") : String8("tool"));        runtime.setClassNameAndArgs(className, argc - i, argv + i);    } else {        // We're in zygote mode.        maybeCreateDalvikCache();        if (startSystemServer) {            args.add(String8("start-system-server"));        }        char prop[PROP_VALUE_MAX];        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",                ABI_LIST_PROPERTY);            return 11;        }        String8 abiFlag("--abi-list=");        abiFlag.append(prop);        args.add(abiFlag);        // In zygote mode, pass all remaining arguments to the zygote        // main() method.        for (; i < argc; ++i) {            args.add(String8(argv[i]));        }    }     // ******************** 第六部分 *********************      if (!niceName.isEmpty()) {        runtime.setArgv0(niceName.string());        set_process_name(niceName.string());    }     // ******************** 第七部分 *********************  启动Java类,如果启动参数带有 "--zygote"。则执行ZygoteInit。    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.");        return 10;    }}
  • 初始化AppRuntime,AppRuntime继承于AndroidRuntime
  • 解析传入参数
  • 根据参数启动Zygote:从init.rc传入的参数 为-Xzygote /system/bin --zygote --start-system-server
    -Xzygote是传递给虚拟机的参数
    /system/bin 是 parent dir(程序运行目录)
    启动参数带有 "--zygote"。则执行ZygoteInit。

在解析完参数后,最终调用:com.android.internal.os.ZygoteInit进行Zygote的初始化

4.3 AppRuntime

AppRuntime继承于AndroidRuntime的构造函数,并且重载了onVmCreated 、onStarted、onZygoteInit和onExit函数。AndroidRuntime初始化时会初始化Skia图形系统.
AndroidRuntime类是安卓底层系统超级重要的一个类,它负责启动虚拟机以及Java线程。AndroidRuntime类是在一个进程中只有一个实例对象,并将其保存在全局变量gCurRuntime中。

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :        mExitWithoutCleanup(false),        mArgBlockStart(argBlockStart),        mArgBlockLength(argBlockLength){    SkGraphics::Init();    // Pre-allocate enough space to hold a fair number of options.    mOptions.setCapacity(20);    assert(gCurRuntime == NULL);        // one per process    gCurRuntime = this;}

SkGraphics::Init();:
这里主要是初始化skia图形系统。skia是google的第一个底层的图形、图像、动画、SVG、文本等多方面的图形图,是Android图形系统的引擎。skia作为第三方软件放在external目录下: external/skia/。后面附了一个skia结构图
mOptions.setCapacity(20);:预先分配空间来存放传入虚拟机的参数
gCurRuntime = this;:首先通过的断言判断gCurRuntime是否为空,保证只能被初始化一次

AppRuntime类:

class AppRuntime : public AndroidRuntime{public:    AppRuntime(char* argBlockStart, const size_t argBlockLength)        : AndroidRuntime(argBlockStart, argBlockLength)        , mClass(NULL)    {    }    

AppRuntime启动zygote时调用的是AndroidRuntime的start函数
className的值是“com.android.internal.os.ZygoteInit"

/* * Start the Android runtime.  This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". * * Passes the main function two arguments, the class name and the specified * options string. */void AndroidRuntime::start(const char* className, const Vector& options, bool zygote){    //******************* 第一部分**********************第一部分——打印log首先调用了ALOGD方法,用来记录日内容(ALOGD记录的日志在编译的时候时候存在,但是在运行时会被提出),标志着Android的启动。后面跟着的for循环,来判断是否是启动systemServer(即传入的参数是或否有startSystemServer),如果是启动systemServer,同样要打印日志。    ALOGD(">>>>>> START %s uid %d <<<<<<\n",            className != NULL ? className : "(unknown)", getuid());    static const String8 startSystemServer("start-system-server");    /*     * 'startSystemServer == true' means runtime is obsolete and not run from     * init.rc anymore, so we print out the boot start event here.     */    for (size_t i = 0; i < options.size(); ++i) {        if (options[i] == startSystemServer) {           /* track our progress through the boot sequence */           const int LOG_BOOT_PROGRESS_START = 3000;           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));        }    }     //******************* 第二部分**********************第二部分——获取系统目录系统目录从环境变量ANDROID_ROOT中读取。如果说去失败,则默认设置目录为"/system"。如果连"/system"也没有,则Zygote进程会退出。    const char* rootDir = getenv("ANDROID_ROOT");    if (rootDir == NULL) {//如果环境变量中没有,则新增该变量,并设置为/system        rootDir = "/system";        if (!hasDir("/system")) {            LOG_FATAL("No root directory specified, and /android does not exist.");            return;        }        setenv("ANDROID_ROOT", rootDir, 1);    }    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);    //******************* 第三部分**********************通过jni_invocation.Init(NULL)完成jni接口的初始化。接着是创建虚拟机的代码,即调用startVm函数。    /* start the virtual machine */    JniInvocation jni_invocation;    jni_invocation.Init(NULL);    JNIEnv* env;    if (startVm(&mJavaVM, &env, zygote) != 0) {        return;    }    //******************* 第四部分**********************    onVmCreated(env);    //******************* 第五部分**********************##### 第五部分——注册系统的JNI函数startReg()函数通过调用register_jni_procs()函数将全局的gRegJNI中的本地JNI函数在虚拟机中注册,这部分的解析请参考[3、Android跨进程通信IPC之3——关于"JNI"的那些事](https://www.jianshu.com/p/cd038167d896)中的**4、JNI查找方式**    /*     * Register android functions.     */    if (startReg(env) < 0) {        ALOGE("Unable to register all android natives\n");        return;    }   //******************* 第六部分**********************    /*为启动Java类的main函数做准备     * We want to call main() with a String array with arguments in it.     * At present we have two arguments, the class name and an option string.     * Create an array to hold them.     */    jclass stringClass;    jobjectArray strArray;    jstring classNameStr;    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);    }   //******************* 第七部分**********************    /*调用Zygoteinit类的main()函数     * Start VM.  This thread becomes the main thread of the VM, and will     * not return until the VM exits.     */    char* slashClassName = toSlashClassName(className);    jclass startClass = env->FindClass(slashClassName);    if (startClass == NULL) {        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);        /* keep going */    } 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 {            env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0            if (env->ExceptionCheck())                threadExitUncaughtException(env);#endif        }    }    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");}   

start函数主要做了以下操作:
1、创建了一个JniInvocation的实例,并且调用它的成员函数init来初始化JNI环境。
2、调用AndroidRuntime类的成员函数startVm来创建一个虚拟机即其对应的JNI接口,即创建一个JavaVM接口和一个JNIEnv接口。
3、有了上述的JavaVM接口和JNIEnv接口之后,就可以在Zygote进程中加载指定的class了。

  • 判断是否启动systemserver
  • 启动虚拟机:startVm,里面的参数在这个函数里面确定的。
  • 注册JNI函数:startReg:后续的java世界采用native方式实现,所以必须提前注册这些函数。
  • 调用JNI函数:
    JNI函数是通过调用startReg()实现,主要是注册gRegJNI[]数组,调用了com.android.internal.os.ZygoteInit类中的main函数

4.4 Zygote

AndroidRuntime.cpp的start()函数里面是调用的Zygoteinit类的main()函数来启动zygote:

    public static void main(String argv[]) {        try {            //**************** 第一阶段 **********************            // 启动DDMS            RuntimeInit.enableDdms();            // Start profiling the zygote initialization.            // 启动性能统计             SamplingProfilerIntegration.start();            boolean startSystemServer = false;            String socketName = "zygote";            String abiList = null;            for (int i = 1; i < argv.length; i++) {                if ("start-system-server".equals(argv[i])) {                    startSystemServer = true;                } else if (argv[i].startsWith(ABI_LIST_ARG)) {                    abiList = argv[i].substring(ABI_LIST_ARG.length());                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());                } else {                    throw new RuntimeException("Unknown command line argument: " + argv[i]);                }            }            if (abiList == null) {                throw new RuntimeException("No ABI list supplied.");            }           //**************** 第二阶段 **********************            registerZygoteSocket(socketName);            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,                SystemClock.uptimeMillis());           //**************** 第三阶段 **********************            preload();            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                SystemClock.uptimeMillis());            // Finish profiling the zygote initialization.            SamplingProfilerIntegration.writeZygoteSnapshot();            // Do an initial gc to clean up after startup            gcAndFinalize();            // Disable tracing so that forked processes do not inherit stale tracing tags from            // Zygote.            Trace.setTracingEnabled(false);           //**************** 第四阶段 **********************            if (startSystemServer) {                startSystemServer(abiList, socketName);            }            Log.i(TAG, "Accepting command socket connections");           //**************** 第五阶段 **********************            runSelectLoop(abiList);            closeServerSocket();        } catch (MethodAndArgsCaller caller) {            caller.run();        } catch (RuntimeException ex) {            Log.e(TAG, "Zygote died with exception", ex);            closeServerSocket();            throw ex;        }    }
zygote启动分析

我将ZygoteInit的main()方法分为5个阶段,阶段解析如下:
第一阶段:主要是解析调用的参数,即argv[],通过for循环遍历解析,通过string的方法来判断,主要出是初始化startSystemServer、abiList和socketName变量
第二阶段:调用registerZygoteSocket(socketName)方法注册Zygote的socket监听接口,用来启动应用程序的消息。建立IPC通信服务端。
第三阶段:调用preload()方法装载系统资源,包括系统预加载类、Framework资源和openGL的资源。这样当程序被fork处理后,应用的进程内已经包含了这些系统资源,大大节省了应用的启动时间。
第四阶段:调用startSystemServer()方法启动SystemServer进程。所有的服务,都在startsystemserver中创建出来。这个函数会创建Java世界中系统Service所驻留的进程 system_server,该进程是framework的核心。
第五阶段:调动runSelectLooper方法进入监听和接收消息的循环

preload

为了加快应用程序的启动,Android把系统公用的Java类和一部分Framework的资源保存在zygote中了,这样就可以保证zygote进程fork子进程的是共享的。


预加载
zygote预加载资源

预加载系统的类。
预加载资源:图片和颜色设置。保存在全局变量中。
如颜色:mResources.getColorStateList(id)。

zygote预加载目的

zygote:提前加载后,使用fork时继承系统资源,然后用java方法进行启动,这样应用不用重新加载资源和类,可以提高应用启动和运行速度。


image.png

加载系统资源,首先创建一个resources,保存系统的资源。导入类的配置文件。最后class.forname,进行加载。

启动systemserver

Zygote类的main()方法里面的第四阶段调用startSystemServer启动系统服务,代码在zygoteinit.java中,

zygote创建system_server主要方法

1、为fork准备参数parsedArgs
2、调用Zygote.forkSystemServer()方法来创建system_server
3、调用handleSystemServerProcess()方法执行system_server的剩余工作

forksystemserver创建子进程的过程中,调用native方法来相关信号的处理。在子进程中调用handlesystemserverprocess。

  1. 关闭Zygote的socket两端的连接
    在fork过程中复制了原来位于zygote进程的socket服务端,这里关闭了从父进程复制而来的socket
    在关闭和子进程退出的时候,用来关闭并清理zygote的socket,
  2. 通过设置umask创建文件的默认权限
    3、设置进程名字 ,即设置当前进程名为"system_server"
    4、获取SYSTEMSERVERCLASSPATH环境变量值(一系列jar),如果需要,则进行dex优化
    5、最后一步,也是最重要的一步:由于invokeWith为null,所以
    会通过RuntimeInit.zygoteInit中调用applicationInit,进而调用invokeStaticMain,然后就会调用SystemServer的main()方法,下面会详细讲解的
Zygote.forkSystemServer()函数解析

主要是调用nativeForkSystemServer方法,通过C层来实现创建system_server进程。在
nativeForkSystemServer中调用ForkAndSpecializeCommon函数来fork子进程。
在ForkAndSpecializeCommon中,有三个核心函数,即SetSigChldHandler()与UnsetSigChldHandler()函数、fork()函数和zygote.callPostForkChildHooks()函数,

handleSystemServerProcess()函数解析

完成fork后新的system server进程的剩余工作

RuntimeInit.zygoteInit函数解析

在调用applicationInit方法前进行一些初始化操作,即日志重定向和zygote初始化
调用applicationInit进行应用初始化

256    /**257     * The main function called when started through the zygote process. This258     * could be unified with main(), if the native code in nativeFinishInit()259     * were rationalized with Zygote startup.

269 public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)270 throws ZygoteInit.MethodAndArgsCaller {271 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");272273 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); // 日志重定向274 redirectLogStreams(); // 通用的初始化工作276 commonInit(); // zygote初始化277 nativeZygoteInit(); // 应用的初始化278 applicationInit(targetSdkVersion, argv, classLoader);279 }

invokeStaticMain函数解析(runtimeinit.java中)

调用目标类className类的静态main(argv []) 方法。将各种失败异常转化为RuntimeExceptions,并且这些异常将会导致VM实例退出。该函数最后一句抛出异常的语句,根据注释,这个ZygoteInit.MethodAndArgsCaller的"异常"会被ZygoteInit.main()捕获。
在ZygoteInit.main中,

public static void main(String argv[]) {    try {        ....    } catch (MethodAndArgsCaller caller) {        caller.run();    } catch (RuntimeException ex) {        closeServerSocket();        throw ex;    }}
zygote创建system_server

startsystemserver创建子进程。
异常被catch捕获,

  1. 创建子进程
  2. 设置子进程相关函数
  3. 完成systemserver启动的参数,包括类名和入口函数,然后抛出异常,然后被捕获异常并启动systemserver。

zygote 创建app,处理启动应用的请求

ZygoteInit类的main()方法调用runSelectLoop()方法来监听和处理启动应用的请求

zygote 创建应用
前面提到了注册IPC socket,这里将使用到。

654    /**655     * Runs the zygote process's select loop. Accepts new connections as656     * they happen, and reads commands from connections one spawn-request's657     * worth at a time.658     *659     * @throws MethodAndArgsCaller in a child process when a main() should660     * be executed.661     */662    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {663        ArrayList fds = new ArrayList();664        ArrayList peers = new ArrayList();665         # fds[0]为sServerSocket,即sServerSocket为位于zygote进程中的socket服务端666        fds.add(sServerSocket.getFileDescriptor());667        peers.add(null);668669        while (true) {//************************** 第1部分   ************************** 670            StructPollfd[] pollFds = new StructPollfd[fds.size()];671            for (int i = 0; i < pollFds.length; ++i) {672                pollFds[i] = new StructPollfd();                   // pollFds[0].fd即为sServerSocket,位于zygote进程中的socket服务端。673                pollFds[i].fd = fds.get(i);674                pollFds[i].events = (short) POLLIN;675            }676            try {                   // 查询轮训状态,当pollFdd有事件到来则往下执行,否则阻塞在这里677                Os.poll(pollFds, -1);678            } catch (ErrnoException ex) {679                throw new RuntimeException("poll failed", ex);680            }681            for (int i = pollFds.length - 1; i >= 0; --i) {                 // 采用I/O 多路复用机制,当接受到客户端发出的连接请求,或者处理出具时,则往下执行                 // 否则进入continue,跳出本次循环 682                if ((pollFds[i].revents & POLLIN) == 0) {683                    continue;684                }//************************** 第2部分   **************************685                if (i == 0) {                      // 客户端第一次请求服务端,服务端调用accept与客户端建立连接,客户端在zygote以ZygoteConnection对象表示686                    ZygoteConnection newPeer = acceptCommandPeer(abiList);687                    peers.add(newPeer);688                    fds.add(newPeer.getFileDesciptor());689                } else {//*************************** 第3部分   **************************                      // 经过上个if操作后,客户端与服务端已经建立连接,并开始发送数据                      //peers.get(index)取得发送数据客户端的ZygoteConnection对象                      // 然后调用runOnce()方法来出具具体请求690                    boolean done = peers.get(i).runOnce();691                    if (done) {692                        peers.remove(i);                           // 处理完则从fds中移除该文件描述符693                        fds.remove(i);694                    }695                }696            }697        }698    }
runonce

从socket中读取一个启动命令,如果成功,则在fork一个子进程,并在在子进程中抛出一个异常,但是在父进程中是正常返回的。如果失败,子进程不会被fork出来,并且把错误信息会被答应在日志中。这里会返回一个布尔的状态值,表示是否结束socket。

返回值 false:如果socket还能继续读取,则返回false,如果读取结束,则返回true

zygote创建应用流程
  1. 调用readArgumentList()方法从socket连接中读入个多个参数
  2. 读取完毕后,调用Arguments有参构造函数,new一个Arguments 对象即parsedArgs。将上面的参数解析成列表。这个列表对象就是parsedArgs
  3. 解析完参数后,还要对这些参数进行检查和设置。
  4. 参数检查无误后,将调用Zygote类的forkAndSpecialize来fork子进程
  5. 上面结束后,如果返回的pid等于0,表示处于子进程中,执行handleChildProc(),如果pid不等于0,则表示在zygote进程中,则调用handleParentProc()方法继续处理。

创建socket,监听本地socket,管理好每一个session
解析启动消息,收到connect时,添加session链接,使用android启动的方式进行创建进程。
fds:用以保存我们监听的socket
peers:就是一个session

zygote创建system_server

ZogyteInit的main函数主要操作:

  1. 创建ZogyteServer并标记启动
  2. 设置进程pid和gid为0
  3. 解析参数
  4. 创建本地socket服务
  5. 预加载系统类和资源
  6. fork SystemServer进程
  7. 启动ZogyteServer的selectLoop线程处理子进程的命令
zygote启动流程总结

1 创建AppRuntime对象,并且调用其start函数。之后zygote的核心初始化都由AppRuntime中。
2 调用startVm创建Java虚拟机,然后调用startReg来注册JNI函数
3 通过JNI调用com.android.internal.os.ZygoteInit的main函数,从此进入了Java世界
4 调用registerZygoteSocket创建可以响应子孙后台请求的socket。同时zygote调用preload函数预加载常用的类、资源等,为Java世界添砖加瓦
5 调用startSystemServer函数fork一个system_server来为Java服务
6 Zygote完成了Java的初始工作后,便调用runSelectLoop来让自己无限循环等待。之后,如果收到子孙后代的请求,它便会醒来为他们工作。

zygote

5.0、SystemServer 启动介绍

ZygoteInit中handleSystemServerProcess函数的最后一步,会调用startSystemServer()函数,该函数是system_server启动流程的起点

systemserver启动流程图

上图前4步骤(即颜色为紫色的流程)运行在是Zygote进程,
从第5步(即颜色为蓝色的流程)ZygoteInit.handleSystemServerProcess开始是运行在新创建的system_server,这是fork机制实现的(fork会返回2次)。下面从startSystemServer()开始讲解详细启动流程

5.01~5.05 创建systemserver进程

5.01 startsystemserver

这个里面有开启system_server进程。

//位于ZygoteInit.javaprivate static boolean startSystemServer(String abiList, String socketName)            throws MethodAndArgsCaller, RuntimeException {        ...        // 准备启动参数        String args[] = {            "--setuid=1000",            "--setgid=1000",            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",            "--capabilities=" + capabilities + "," + capabilities,            "--nice-name=system_server", //进程名            "--runtime-args",            "com.android.server.SystemServer",//启动的类名        };        ZygoteConnection.Arguments parsedArgs = null;        ...        int pid;        try {            ...// fork一个紫禁城,这个就是system_server进程            pid = Zygote.forkSystemServer(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        // 进入子进程system_server        if (pid == 0) {            if (hasSecondZygote(abiList)) {                waitForSecondaryZygote(socketName);            }            // 完成system_server进程剩余的工作            handleSystemServerProcess(parsedArgs);        }        return true;    }

这里,zygote进行了一次无性繁殖,分类除了system_server(zygote.forksystemserver)。
准备参数并fork新进程,从上面可以看出system server进程参数信息为uid=1000,gid=1000,进程名为sytem_server,从zygote进程fork新进程后,需要关闭zygote原有的socket。另外,对于有两个zygote进程情况,需等待第2个zygote创建完成。

5.02 forkSystemServer

该函数是一个native函数

public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {    VM_HOOKS.preFork();    // 调用native方法fork system_server进程【见小节3】    int pid = nativeForkSystemServer(            uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);    if (pid == 0) {        Trace.setTracingEnabled(true);    }    VM_HOOKS.postForkCommon();    return pid;}

nativeForkSystemServer()方法在AndroidRuntime.cpp中注册的,调用com_android_internal_os_Zygote.cpp中的register_com_android_internal_os_Zygote()方法建立native方法的映射关系,所以接下来进入如下方法。

5.03. nativeForkSystemServer

static jint com_android_internal_os_Zygote_nativeForkSystemServer(        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,        jlong effectiveCapabilities) {  //fork子进程,见【见小节4】  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,                                      debug_flags, rlimits,                                      permittedCapabilities, effectiveCapabilities,                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,                                      NULL, NULL);  if (pid > 0) {      // zygote进程,检测system_server进程是否创建      gSystemServerPid = pid;      int status;      if (waitpid(pid, &status, WNOHANG) == pid) {          //当system_server进程死亡后,重启zygote进程          RuntimeAbort(env);      }  }  return pid;}

在ForkAndSpecializeCommon()函数中将调用fork()函数来创建子进程之前还调用了SetSigChldHandler函数设置处理SIGCHLD信号的函数SigChldHandler()。

5.04 ForkAndSpecializeCommon

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jstring instructionSet, jstring dataDir) { # 设置子进程的signal信号处理函数  SetSigChldHandler();   pid_t pid = fork(); //fork子进程  if (pid == 0) {    //进入子进程    DetachDescriptors(env, fdsToClose); //关闭并清除文件描述符    if (!is_system_server) {        //对于非system_server子进程,则创建进程组        int rc = createProcessGroup(uid, getpid());    }    SetGids(env, javaGids); //设置设置group    SetRLimits(env, javaRlimits); //设置资源limit    int rc = setresgid(gid, gid, gid);    rc = setresuid(uid, uid, uid);    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);    SetSchedulerPolicy(env); //设置调度策略     //selinux上下文    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);    if (se_info_c_str == NULL && is_system_server) {      se_name_c_str = "system_server";    }    if (se_info_c_str != NULL) {      SetThreadName(se_name_c_str); //设置线程名为system_server,方便调试    }    UnsetSigChldHandler(); //设置子进程的signal信号处理函数为默认函数    //等价于调用zygote.callPostForkChildHooks()    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,                              is_system_server ? NULL : instructionSet);    ...  } else if (pid > 0) {    //进入父进程,即zygote进程  }  return pid;}

fork()创建新进程,采用copy on write方式,这是linux创建进程的标准方法,会有两次return,对于pid==0为子进程的返回,对于pid>0为父进程的返回。 到此system_server进程已完成了创建的所有工作,接下来开始了system_server进程的真正工作。在前面startSystemServer()方法中,zygote进程执行完forkSystemServer()后,新创建出来的system_server进程便进入

SetSigChldHandler函数

在ForkAndSpecializeCommon()函数中将调用fork()函数来创建子进程之前还调用了SetSigChldHandler函数设置处理SIGCHLD信号的函数SigChldHandler()。

static void SigChldHandler(int /*signal_number*/) {  pid_t pid;  ...  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {    ...    if (pid == gSystemServerPid) {      ALOGE("Exit zygote because system server (%d) has terminated", pid);      kill(getpid(), SIGKILL); // 如果死亡的是SystemServer进程,zygote将退出    }  }  ...}

SigChldHandler函数接收到子进程死亡的信号后,除了调用waitpid()来防止子进程变“僵尸”外,还会判断死亡的子进程是否是SystemServer进程,如果是,Zygote进程会“自杀”,这样将导致Init进程杀死所有用户进程并重启Zygote。整个手机相当于重启了一扁,从而达到系统“软重启”的目的。

5.05 handleSystemServerProcess(systemserver的使命)

这个函数调用在startsystemserver中,在fork出SystemServer进程后(handleSystemServerProcess函数的前一个步骤),在fork出的进程中调用handleSystemServerProcess()来初始化SystemServer进程

private static void handleSystemServerProcess(            ZygoteConnection.Arguments parsedArgs)            throws ZygoteInit.MethodAndArgsCaller {        * 关闭父进程zygote复制而来的Socket        closeServerSocket();         /SystemServer进程的umask设为0077(S_IRWXG|S_IRWXO),        /这样SystemServer创建的文件的属性就是0077,只有SystemServer进程可以访问。        Os.umask(S_IRWXG | S_IRWXO);        if (parsedArgs.niceName != null) {            // 设置当前进程名为 "system_server"            Process.setArgV0(parsedArgs.niceName);        }        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");        if (systemServerClasspath != null) {            // 执行dex优化操作            performSystemServerDexOpt(systemServerClasspath);        }        if (parsedArgs.invokeWith != null) {// invokeWith通常为null            String[] args = parsedArgs.remainingArgs;            if (systemServerClasspath != null) {                String[] amendedArgs = new String[args.length + 2];                amendedArgs[0] = "-cp";                amendedArgs[1] = systemServerClasspath;                System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);            }            // 启动应用进程            WrapperInit.execApplication(parsedArgs.invokeWith,                    parsedArgs.niceName, parsedArgs.targetSdkVersion,                    VMRuntime.getCurrentInstructionSet(), null, args);        } else {            ClassLoader cl = null;            if (systemServerClasspath != null) {                //创建类加载器,并赋予当前线程                cl = createSystemServerClassLoader(systemServerClasspath,                                                   parsedArgs.targetSdkVersion);                Thread.currentThread().setContextClassLoader(cl);            }            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);        }    }

因为参数invokeWith通常为null,所以会调用RuntimeInit.zygoteInit()方法。在zygoteInit()方法中,它最终会以抛出MethodAndArgsCaller异常的方式返回,实现真正调用SystemServer类的main()方法。

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");    redirectLogStreams(); //重定向log输出    commonInit(); // 通用的一些初始化SS调用了下面这个函数后,将于Binder通信系统建立联系,这样SS就能使用Binder了    nativeZygoteInit(); // zygote初始化 nativeZygoteInit()方法在AndroidRuntime.cpp中,进行了jni映射    applicationInit(targetSdkVersion, argv, classLoader); // 应用初始化
在applicationinit函数中,调用了invokeStaticMain函数,

抛出一个一场,在zygoteinit的main里被截获。

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {    Class<?> cl = Class.forName(className, true, classLoader);    ...    Method m;    try {        m = cl.getMethod("main", new Class[] { String[].class });    } catch (NoSuchMethodException ex) {        ...    } catch (SecurityException ex) {        ...    }    int modifiers = m.getModifiers();    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {        ...    }    //通过抛出异常,回到ZygoteInit.main()。这样做好处是能清空栈帧,提高栈帧利用率。【见小节12】    throw new ZygoteInit.MethodAndArgsCaller(m, argv);}

现在已经很明显了,在RuntimeInit.java中invokeStaticMain方法通过创建并抛出异常,ZygoteInit.MethodAndArgsCaller,在ZygoteInit.java中的main()方法会捕捉该异常
并调用caller.run(),再通过反射便会调用到SystemServer.main()方法**

5.06 systemserver的初始化

SystemServer是一个java类,其main()方法中调用了对象的run()方法

    public static void main(String[] args) {        //先初始化SystemServer对象,再调用对象的run()方法        new SystemServer().run();    }    private void run() {        try {            //当系统时间比1970年更早,就设置当前系统时间为1970年             if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);            }            if (!SystemProperties.get("persist.sys.language").isEmpty()) {                final String languageTag = Locale.getDefault().toLanguageTag();                SystemProperties.set("persist.sys.locale", languageTag);                SystemProperties.set("persist.sys.language", "");                SystemProperties.set("persist.sys.country", "");                SystemProperties.set("persist.sys.localevar", "");            }            //变更虚拟机的库文件,对于Android 6.0默认采用的是libart.so            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());            if (SamplingProfilerIntegration.isEnabled()) {                SamplingProfilerIntegration.start();                mProfilerSnapshotTimer = new Timer();                //system_server每隔1小时采用一次,并保存结果到system_server文件                mProfilerSnapshotTimer.schedule(new TimerTask() {                        @Override                        public void run() {                            SamplingProfilerIntegration.writeSnapshot("system_server", null);                        }                    }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);            }            VMRuntime.getRuntime().clearGrowthLimit();            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);            Build.ensureFingerprintProperty();            Environment.setUserRequired(true);            BaseBundle.setShouldDefuse(true);            BinderInternal.disableBackgroundScheduling(true);            BinderInternal.setMaxThreads(sMaxBinderThreads);            android.os.Process.setThreadPriority(                android.os.Process.THREAD_PRIORITY_FOREGROUND);            android.os.Process.setCanSelfBackground(false);            // 主线程looper就在当前线程运行            Looper.prepareMainLooper();            //加载android_servers.so库,该库包含的源码在frameworks/base/services/目录下            System.loadLibrary("android_servers");            // 检查上次关机过程是否失败,该方法可能不会返回            performPendingShutdown();            // 初始化系统上下文            createSystemContext();            //创建系统服务管理            mSystemServiceManager = new SystemServiceManager(mSystemContext);            //将mSystemServiceManager添加到本地服务的成员sLocalServiceObjects            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);        }        // 创建并运行所有的Java服务        try {            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");            startBootstrapServices();   //启动引导服务            startCoreServices();        //启动核心服务            startOtherServices();       //启动其它服务        } catch (Throwable ex) {            throw ex;        } finally {            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);        }        // 进入处理消息的循环        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }

main()方法的主要是有:
1.调用时间,如果当前系统时间比1970年更早,就设置当前系统时间为1970年 。
2.设置属性persist.sys.dalvik.vm.lib.2的值为当前虚拟机的运行库的路径。
3.调整虚拟机堆的内存。设定虚拟机利用率为0.8。
4.加载android_servers.so库。

5.调用createSystemContext()来获取Context。
6.创建SystemServiceManager的对象mSystemServiceManager,这个对象负责系统Service的启动。
7.启动服务。startBootstrapServices(),startCoreServices()和 startOtherServices()创建并运行所有Java服务。
8.调用Loop.loop(),进入处理消息的循环。

这里重点是:

  1. 调用createSystemContext()来创建系统上下文
  2. 创建SystemServiceManager
  3. 启动各种服务
    private void createSystemContext() {        //创建ActivityThread对象        ActivityThread activityThread = ActivityThread.systemMain();        //创建ContextImpl、LoadedApk对象        mSystemContext = activityThread.getSystemContext();        //设置主题        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);    }

在createSystemContext()方法里,通过ActivityThread的静态方法systemMain()创建了一个activityThread。然后调用它的getSystemContext()方法来获取系统的Context,最后设置主题。

然后来分析systemmain
    public static ActivityThread systemMain() {        //对于低内存的设备,禁用硬件加速        if (!ActivityManager.isHighEndGfx()) {            ThreadedRenderer.disable(true);        } else {            ThreadedRenderer.enableForegroundTrimming();        }        // 创建ActivityThread        ActivityThread thread = new ActivityThread();        // 创建Application以及调用其onCreate()方法        thread.attach(true);//代表是系统的应用进程        return thread;    }

上面的代码主要是new了一个ActivityThread对象。
同样的我们知道,ActivityThread是应用程序的主线程类,该类同时也存在一个main()主方法,zygote进程在启动过程的最后会在抛出的MethodAndArgsCaller异常中,通过反射来执行ActivityThread类的main()方法。那么这里为什么要用new来创建ActivityThread对象呢?
实际上SystemServer不仅是一个单纯的后台进程,它也是一个运行着组件Service的进程,很多系统的对话框就是从SystemServer中显示出来的,因此,SystemServer本身也需要一个和APK应用类似的上下文环境,创建ActivityThread是获取这个环境的第一步,后面还需要创建SystemContext对象。ActivityThread的attach(boolean)方法中,传入参数true时,表示是在SystemServer中调用。如下代码:

    private void attach(boolean system) {        sCurrentActivityThread = this;        mSystemThread = system;        if (!system) {//进入应用进程的处理流程            ...        } else { //进入系统进程。该情况只在SystemServer中处理,设置DDMS时看到的systemserver进程名为system_process            android.ddm.DdmHandleAppName.setAppName("system_process",                    UserHandle.myUserId());            try {                mInstrumentation = new Instrumentation();                // 创建应用上下文SystemContext                ContextImpl context = ContextImpl.createAppContext(                        this, getSystemContext().mPackageInfo);                // 创建Application                mInitialApplication = context.mPackageInfo.makeApplication(true, null);                // 调用Application的onCreate()方法                mInitialApplication.onCreate();            } catch (Exception e) {                throw new RuntimeException(                        "Unable to instantiate Application():" + e.toString(), e);            }        }        ...    }

system为true时,创建了ContextImpl和Application对象,最后还调用了Application的onCreate()方法,完全模拟创建一个应用的过程。但是,创建应用上下文环境需要对应的一个apk文件,这个的apk文件是哪个呢?上面的参数中getSystemContext().mPackageInfo正是。
通过跟踪getSystemContext()的代码,最终可以找到在ContextImpl类的createSystemContext(ActivityThread)方法中创建了一个LoadedApk对象。

    LoadedApk(ActivityThread activityThread) {        mActivityThread = activityThread;        mApplicationInfo = new ApplicationInfo();        mApplicationInfo.packageName = "android";        mPackageName = "android";        ...    }

LoadedApk对象保存了一个apk文件的信息,它指明了将使用的包名为“android”,而framework-res.apk的包名正是“android”。因此,getSystemContext()方法返回的对象所对象的apk文件就是framework-res.apk。
因此,ActivityThread的SystemMain()方法相当于创建了一个framework-res.apk的上下文环境

SystemServer是Android系统的核心之一,大部分Android提供的服务都运行在这个进程里,SystemServer中运行的服务总共有60多种。为了防止应用进程对系统造成破坏,Android的应用进程没有权限直接访问设备的底层资源,只能通过SystemService中的代理访问。通过Binder,用户进程在使用SystemService中的服务并没有太多不便变之处。


android 系统服务

5.1 ActivityManagerService 启动

zygote孵化出来的第一个android服务程序(system_server),通过runselectloop等待并处理来之客户的消息,派生启动android系统中所有的核心服务。
activitymanagerservice:核心服务,由systemserver创建

AMS在SystemServer的startBootstrapServices中启动,主要是创建了一个Lifecycle对象创建AMS。
创建AMS后会调用AMS的start方法。setSystemServiceManager方法是把AMS纳入SystemServerManager的管理。
在AMS的构造函数中初始化了很多变量和一些服务,如果管理广播的队列、电池和CPU等相关服务,服务会在start方法中启动,并等待启动完成。
最后,调用AMS的systemReady方法完成初始化,在SystemReady中启动桌面。

// Activity manager runs the show.traceBeginAndSlog("StartActivityManager");mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);traceEnd();
public static final class Lifecycle extends SystemService {    private final ActivityManagerService mService;    public Lifecycle(Context context) {        super(context);        mService = new ActivityManagerService(context);    }    @Override    public void onStart() {        mService.start();    }    @Override    public void onCleanupUser(int userId) {        mService.mBatteryStatsService.onCleanupUser(userId);    }    public ActivityManagerService getService() {        return mService;    }}

systemReady在SystemServer的startOtherServices的最后被调用,主要是动作是标记和等待各个服务启动完成如等待PMS启动结束,接着启动SystemUI和启动HomeActivity。在Android N之后引入DirectBoot,DirectBoot是一种安全模式,是开机完成但用户还没有解锁的时候处于的一种运行环境。

AMS初始化在启动完成后,在锁屏界面Keyguard绘制完成后(finishKeyguardDrawn),然后调用WindowManagerService的enableScreenAfterBoot,WMS会接着调用performEnableScreen通知SurfaceFlinger关闭开机动画,接着WMS调用AMS的bootAnimationComplete通知AMS开机动画结束,AMS最后通过调用finishBooting设置属性sys.boot_complete通知系统开机完成,可以执行属性sys.boot_complete设置之后的任务

WMS与SurfaceFlingerBinder进行Binder通信的协议:

可以看到WMS通过binder通信,调用IBinder.FIRST_CALL_TRANSACTION函数,也就是android.ui.ISurfaceComposer的BOOT_FINISHED对应的函数bootFinished(),SurfaceFlinger是继承BpSurfaceComposer的,所以最后调用的是SurfaceFlinger::bootFinished(),通过设置属性service.bootanim.exit标记开机动画结束

android system服务启动过程

initandloop:把所有的服务一条一条的初始化完成,加到servermanager中,加载之后,调用loop方法中,处理一些消息。主要的工作都在这个函数里 。

nativeinit:frameworks/base/services/jni/com_android_server_systemserver.cpp
SystemServer需要从Zygote fork SystemServer开始分析,主要是设置参数,然后调用Zygote的forkSystemServer方法,再判断是否有SecondaryZygote启动,有则等待其启动,无则返回

Zygote的forkSystemServer方法主要是调用了native方法nativeForkSystemServer,在native层进行fork动作,并设置pid、gid、selinux安全上下文等,最后启动com.android.server.SystemServer

public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,        int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {    VM_HOOKS.preFork();    // Resets nice priority for zygote process.    resetNicePriority();    int pid = nativeForkSystemServer(            uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);    // Enable tracing as soon as we enter the system_server.    if (pid == 0) {        Trace.setTracingEnabled(true, debugFlags);    }    VM_HOOKS.postForkCommon();    return pid;}

log 抓取与分析风阀

开机时间主要分析kernel log、events log、logcat log

adb shell dmesg > dmesg.txtadb logcat –v threadtime –b events –d > logcat_events.logadb logcat –v threadtime –d *:V > logcat.txt

更多相关文章

  1. android原生和H5交互(转)
  2. 《浅谈android进程》
  3. Android(安卓)电池管理系统
  4. Android(安卓)call setting 源码分析 从顶层到底层(下)
  5. 小熊android学习总结:Linux内核怎样启动Android
  6. Android(安卓)Service组件(1)
  7. Qt on Android:将Qt调试信息输出到logcat中
  8. Android(安卓)Media (Audio) Framework Analyse
  9. Android(安卓)NDK 使用第一步,编译c文件,声明jni并调用。

随机推荐

  1. android 加载进度条动画
  2. android alarm相关信息
  3. Android(安卓)时间戳和时间之间的转化
  4. android segment fault logcat相关信息分
  5. [Android(安卓)UI界面] 怎样实现ListView
  6. Android存储设备管理
  7. android实现虚拟按键实例
  8. Android中两个HorizontalScrollView联动
  9. 根据文本生成位图
  10. android 定制对话框 Layoutlnflater