1, 概述
Android系统启动流程图如下,
1,Bootloader引导
当手机按下电源键时,最先运行的就是bootloader。主要作用是初始化基本的硬件环境(如CPU,内存,Flash等),为装载Linux内核准备合适的运行环境。一旦Linux内核装载完毕,bootloader将会从内存中清除掉。
Fastboot 是android设计的一套通过USB更新手机分区映像的协议,方便开发人员快速更新指定的手机分区。
Recovery 是android特有的升级系统。手机可以进行恢复出厂设置或者执行OTA,补丁和固件升级等操作。
2,Linux内核
Android的boot.img存放的就是Linux内核和一个跟文件系统。Bootloader会把boot.img映像装进内存,然后Linux内核会执行整个系统的初始化,完成后装载跟文件系统,最后启动init进程。
3,init进程
Init进程是android系统的第一个用户空间进程,它的进程号为1.主要作用如下,
A,启动android系统中重要的守护进程(USB守护进程,adb,vold,rild等守护进程)
B,启动Zygote进程,会创建Dalivik虚拟机,创建SystemServer进程,响应应用程序的请求。
C,启动ServiceManager,主要用于管理Binder服务,负责Binder服务的注册和查找。
2 init进程的初始化
Init进程的源码位于/system/core/init/下,程序的入口函数main()位于文件init.cpp中。
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv); // 执行守护进程ueventd的主函数
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv); // 执行看门狗守护进程的主函数
}
umask(0); // 参数为0表示进程创建的文件属性是0777
Init进程代码里包含了另外2个守护进程的代码.
Android.mk文件的部分如下,
# Create symlinks
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdog
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);
}
selinux_initialize(is_first_stage); // 初始化SELinux
init_parse_config_file("/init.rc"); // 解析 init.rc 文件
action_for_each_trigger("early-init", action_add_queue_tail);
// 将指定的action加入到action_queue 中
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
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");
queue_builtin_action(keychord_init_action, "keychord_init");
queue_builtin_action(console_init_action, "console_init");
•••
while (true) {
if (!waiting_for_exec) {
execute_one_command();
restart_processes(); // 启动服务进程
}
3 解析启动脚本init.rc
3.1init.rc文件介绍
Init.rc脚本使用的是一种初始化语言,其中包含了4类声明:
1)Action
2)Command
3)Service
4)Option
该语言规定,Action和Service是以一种“小节”(Section)的形式出现的,其中每个Action小节可以含有若干Command,而每个Service小节可以含有若干Option。小节只有起始标记,却没有明确的结束标记,也就是说,是用“后一个小节”的起始来结束“前一个小节”的。
脚本中的Action大体上表示一个“行动”,它用一系列Command共同完成该“行动”。Action需要有一个触发器(trigger)来触发它,一旦满足了触发条件,这个Action就会被加到执行队列的末尾。Action的形式如下:
on <trigger> // trigger 是触发器
<command1> // 命令
<command2>
例如,