【2017年学习输出内容记录】Android系统启动流程-Android的Init进程

本文详细介绍了Android系统从Linux内核启动到Init进程的整个过程。讲解了Bootloader的三种模式,Linux内核如何加载Init进程,以及Init进程的主要任务,包括创建基本目录、挂载文件系统、初始化属性系统、启动服务等。最后,文章阐述了init.rc文件的作用和内容,展示了如何解析和执行init.rc来启动系统服务。
摘要由CSDN通过智能技术生成
Android系统启动流程-Android的Init进程


一、Linux内核启动

1、启动电源以及系统启动
当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。

2、引导程序Bootloader
Bootloader是在操作系统运行之前运行的一段程序,它是运行的第一个程序,因此它是针对特定的主板与芯片的。它不是Android操作系统的一部分,而是OEM厂商或者运营商加锁和限制的地方。它将系统的软硬件环境带到一个合适的状态,为运行操作系统做好准备。类似于电脑上的BIOS,其目的就是要把OS拉起来运行。Booloader有三种模式:
1)开机后按组合键启动到fastboot模式,即命令或SD卡烧写模式,不加载内核及文件系统,可以通过数据线与电脑连接,然后在电脑上执行一些命令,如刷系统镜像到手机上。
2)开机后按组合键启动到recovery模式,加载recovery.img,recovery.img包含内核、部分系统文件,可以读取sdcard中的update.zip进行刷机,也可以清楚cache和用户数据。
3)开机按Power正常启动系统,加载boot.img。boot.img包含内核、基本文件系统,用于正常启动手机。
Bootloader做的事情主要有:初始化CPU时钟、内存、串口等;设置Linux启动参数;加载Linux各种内核镜像到SDRAM中。

3、Linux内核启动
内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。

4、init进程启动
Init进程是一个由内核启动的用户级进程,可以把它看做是root进程或者说所有进程的父进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init进程有两个责任,一是挂载目录,比如/sys,/dev,/proc,二是运行init.rc脚本。

二、Init进程
1、init入口函数:system/core/init/init.cpp main

int main(int argc, char** argv) {
// (1)首先检查启动程序的文件名
// 如果文件名为:ueventd,执行守护进程ueventd的主函数ueventd_main。
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
// 大致同上
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
// (2)缺省情况下一个进程创建出的文件和文件夹属性是022,使用umask()函数能设置文件属性
// 的掩码。参数为0意味着进程创建的文件属性是0777。
// Clear the umask.
umask(0);

add_environment("PATH", _PATH_DEFPATH);


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) {
// (3)创建一些基本的目录;同时把一些文件系统Mount到相应的目录。
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);//用于把系统的设备和总线按层次组织起来
}

// 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.
// (4)把标准输入、标准输出和标准错误重定向到空设备文件/dev/_null_    
open_devnull_stdio();
// (5)创建节点/dev/_msg_,这样init进程可以使用kernel的log系统来输出log
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);


NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");

if (!is_first_stage) {
// (6)在/dev目录下创建一个空文件.booting表示初始化正在进行,is_booting函数将依
// 靠.booting来判断进程是否处于初始化中
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
// (7)初始化Android属性系统。创建一个共享区域来存储属性值。
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.
process_kernel_dt();
// (8)解析kernel的启动参数,通常放在/proc/cmdline中,利用解析结果参数中的值设置几个属性值
process_kernel_cmdline();


// Propagate the kernel variables to internal variables
// used by init as well as the current required properties.
export_kernel_boot_props();
}

// Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
// (9)初始化SElinux
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) {
if (resto
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值