android开机过程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、Android开机启动流程简介
1、OS-level:
由bootloader载入linux kernel后kernel开始初始化, 并载入built-in 的驱动程序。Kernel完成开机后,载入init process,切换至user-space。
Init进程是第一个在user-space启动的进程。
2、Android-level:
由init process读取init.rc,Native 服务启动,并启动重要的外部程序,例如:servicemanager、Zygote以及System Server等。
由 init process 根据硬件类型读取init.xxx.rc。由init.xxx.rc加载init.xxx.sh。
由 init.xxx.sh 加载特定的硬件驱动。如hi_tuner.ko、hi_demux.ko等。
3、Zygote-Mode:
Zygote 启动完SystemServer 后,进入Zygote Mode,在Socket 等候命令。
随后,使用者将看到一个桌面环境(Home Screen)。桌面环境由一个名为[Launcher]的应用程序负责提供。
本文档重点研究Android-level中的启动流程。
启动流程如下图所示:
二、init process流程分析
init进程简介
init进程是第一个在user-space启动的进程。由内核启动参数[init]传递给内核,如果该项没有设置,内核会按
/etc/init,/bin/init,/sbin/init,/bin/sh的顺序进行尝试,如果都有的都没找到,内核会抛出 kernel panic:的错误。
init进程包含在跟文件系统中,跟文件系统被直接编译到了内核。对init 进程的修改,需要重新编译烧写内核。编译命令:
#cd kernel
#make uImag
CONFIG_INITRAMFS_SOURCE=../out/target/product/Hi3716C/root/ -j 8
#cp kernel/arch/arm/boot/uImage out/target/product/Hi3716C/kernel -afv 源代码路径:
froyo\system\core\init
编译的文件:
builtins.c
init.c
devices.c
property_service.c
util.c
parser.c
logo.c
编译命令:
make init
生成的文件:
/out/target/product/Hi3716C/root/init
init进程启动流程
1.安装SIGCHLD信号。
sigaction(SIGCHLD, &act, 0);
如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。因此需要对SIGCHLD信号做出处理,回收僵尸进程的资源,避免造成不必要的资源浪费。
2.对umask进行清零。
umask(0);
umask是什么?
登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情。umask设置了用户创建文件的默认权限,它与chmod的效果刚好相反,umask设置的是权限“补码”,而chmod设置的是文件权限码。设置文件的默认权限,umask和chmod的权限刚好反的,umask的0000相当于chmod的0777。
3.为rootfs建立必要的文件夹,并挂载适当的分区。
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mount("tmpfs", "/dev", "tmpfs", 0, "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);
4.创建/dev/null和/dev/kmsg节点。
创建/dev/null结点,重定向标准输入,输出以及标准出错。
open_devnull_stdio();
创建/dev/kmsg设备结点,我们可以利用这个设备输出调试信息
log_init();
5.解析/init.rc,将所有服务和操作信息加入链表。
解析初始化脚本,这里只是parse,将脚本解析到一个链表中,并没有执行。
parse_config_file("/init.rc");
6.从/proc/cmdline中提取信息内核启动参数,并保存到全局变量。
qemu_init();
import_kernel_cmdline(0);
7.根据6获得的hardware参数信息,解析额外的硬件相关init脚本.
hi3726c 中为 init.godbox.rc
get_hardware_name();
snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
parse_config_file(tmp);
8.找到init.rc paser链表中为early-init属性的项目,将其添加到action
queue中,并执行执行这些queue中的动作。
action_for_each_trigger("early-init", action_add_queue_tail);
drain_action_queue();
9.遍历/sys文件夹,是内核产生设备添加事件(为了自动产生设备节点)。
device_fd = device_init();
10.初始化属性系统,并导入初始化属性文件。
property_init();
每个属性都有一个名称和值,它们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。在系统初始化时,Android 将分配一个共享内存区来存储的属性,这里主要是从/default.prop属性文件读取属性。类似于像Windows下的注册表的作用。
/default.pro的内容
ro.secure=0
ro.allow.mock.location=1
ro.debuggable=1