Android系统启动_Init

整个Android系统的启动分为Linux Kernel的启动和Android系统的启动。Linux Kernel启动起来后,然后运行第一个用户程序,在Android中就是init程序。

​ init是linux系统中用户空间的第一个进程。由于Android是基于linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1。

1540983920749

init进程的入口文件在system/core/init/init.cpp中,由于init是命令行程序,所以分析init.cpp首先应从main函数开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main(int argc, char** argv) {    // 入口函数main
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}

if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}

// Clear the umask.
umask(0); // 清除屏蔽字(file mode creation mask),保证新建的目录的访问权限不受屏蔽字影响。
add_environment("PATH", _PATH_DEFPATH);

bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0); // 判断是否是系统启动的第一阶段,只有启动参数中有--second-stage才为第二阶段
// 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"); // 挂载tmpfs文件系统
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL); // 挂载devpts文件系统
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); // 挂载proc文件系统
mount("sysfs", "/sys", "sysfs", 0, NULL); // 挂载sysfs文件系统

init的主要职责在于:

  • 创建文件系统目录并挂载相关的文件系统
1
2
3
4
5
6
7
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));
mount("sysfs", "/sys", "sysfs", 0, NULL);
  • 初始化属性,提供property service(属性服务)管理Android系统中的属性
1
property_init();// 初始化属性域 --> 定义于system/core/init/Property_service.cpp
  • 处理配置文件命令(主要是init.rc脚本文件)

    1
    2
    3
    4
    5
    6
    /* 解析init.rc */
    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>());
    parser.ParseConfig("/init.rc");

    init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本,主要包含五种类型语句:Action、Command、Service、Option和Import,在分析代码的过程中我们会详细介绍。

      init.rc的配置代码在:system/core/rootdir/init.rc 中

      init.rc文件是在init进程启动后执行的启动脚本,文件中记录着init进程需执行的操作。

      init.rc文件大致分为两大部分,一部分是以“on”关键字开头的动作列表(action list):

    1
    2
    3
    4
    5
    on early-init      // Action类型语句
    # Set init and its forked children's oom_adj. // #:注释符号
    write /proc/1/oom_score_adj -1000
    ... ...
    start ueventd

    ​ Action类型语句格式:

    1
    2
    3
    on <trigger> [&& <trigger>]*     // 设置触发器  
    <command>
    <command> // 动作触发之后要执行的命令

    ​ 另一部分是以“service”关键字开头的服务列表(service list): 如 Zygote

    1
    2
    3
    4
    5
    6
    7
    8
    service ueventd /sbin/ueventd
    class core
    critical
    seclabel u:r:ueventd:s0

    service dvbserver /vendor/bin/dvbserver
    user root
    group root

    Service类型语句格式:

    1
    2
    3
    4
    service <name> <pathname> [ <argument> ]*   // <service的名字><执行程序路径><传递参数>  
    <option> // option是service的修饰词,影响什么时候、如何启动services
    <option>
    ...

    借助系统环境变量或Linux命令,动作列表用于创建所需目录,以及为某些特定文件指定权限,而服务列表用来记录init进程需要启动的一些子进程。如上面代码所示,service关键字后的第一个字符串表示服务(子进程)的名称,第二个字符串表示服务的执行路径。

值得一提的是在Android 7.0中对init.rc文件进行了拆分,每个服务一个rc文件。我们要分析的zygote服务的启动脚本则在init.zygoteXX.rc中定义。

  在init.rc的import段我们看到如下代码:

1
2
import /init.${ro.zygote}.rc 
//可以看出init.rc不再直接引入一个固定的文件,而是根据属性ro.zygote的内容来引入不同的文件

init.zygote64.rc的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
# class是一个option,指定zygote服务的类型为main
class main
# socket关键字表示一个option,创建一个名为dev/socket/zygote,类型为stream,权限为660的socket
socket zygote stream 660 root system
# onrestart是一个option,说明在zygote重启时需要执行的command
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
writepid /dev/cpuset/foreground/tasks

可以看到zygote的class是main, 它是在on nonencrypted时被启动的,如下:

1
2
3
4
5
on nonencrypted
# A/B update verifier that marks a successful boot.
exec - root cache -- /system/bin/update_verifier nonencrypted
class_start main
class_start late_start

Init.cpp的main函数分析完毕,init进程已经启动完成,一些重要的服务如core服务和main服务也都启动起来,并启动了zygote(/system/bin/app_process64)进程,zygote初始化时会创建虚拟机,启动systemserver等。

原文:https://www.cnblogs.com/pepsimaxin/p/6740413.html