第一阶段的 init 工作主要用于读取系统启动阶段需要的配置信息(例如 linux的bootconfig,cmdline等配置信息)、挂载文件系统、安装 kernel 中的模块驱动,最后就是启动第二阶段的 init 来进行 Android 系统相关的组件。第一阶段的 init 被编译为静态的可执行程序,位于 ramdisk 中。在 kernel 启动后该 init 应用程序则会被运行。
init 可执行程序一般位于 ramdisk 中,而在 Android T 中,包含 init 的 ramdisk 则位于 init_boot.img 镜像中,它在编译 Android时会产生。文件格式和 boot.img 是一致的,所以可以使用 AOSP 编译系统的 unpack_bootimg 来拆包
server :~/AOSP_T/out/target/product/board/tmpImage$ unpack_bootimg --boot_img init_boot.img --out init_boot_unpack_out/
boot magic: ANDROID!
kernel_size: 0
ramdisk size: 2257400
os version: 13.0.0
os patch level: 2023-03
boot image header version: 4
command line args:
boot.img signature size: 0
server :~/AOSP_T/out/target/product/board/tmpImage$ ls - init_boot_unpack_out/
-rw-rw-r-- 1 flgstaff flgstaff 0 Mar 19 16:02 kernel
-rw-rw-r-- 1 flgstaff flgstaff 2257400 Mar 19 16:02 ramdisk
在init_boot中,是没有 linux kernel 的,从它的大小也能看出。下面看下 ramdisk 包含的目录结构,同样的 AOSP 也提供了对应的工具
server :~/AOSP_T/out/target/product/board/tmpImage/init_boot_unpack_out$ export MY_RAMDISK=ramdisk && lz4 -d ${MY_RAMDISK} ${MY_RAMDISK}_d && mkdir ${MY_RAMDISK}Struct && mv ${MY_RAMDISK}_d ${MY_RAMDISK}Struct && cd ${MY_RAMDISK}Struct && cpio -idmv < ${MY_RAMDISK}_d
ramdisk : decoded 4212992 bytes
debug_ramdisk
dev
first_stage_ramdisk
first_stage_ramdisk/debug_ramdisk
first_stage_ramdisk/dev
first_stage_ramdisk/metadata
first_stage_ramdisk/mnt
first_stage_ramdisk/proc
first_stage_ramdisk/second_stage_resources
first_stage_ramdisk/sys
init
metadata
mnt
proc
second_stage_resources
sys
system
system/bin
system/bin/snapuserd
system/etc
system/etc/init
system/etc/init/snapuserd.rc
system/etc/ramdisk
system/etc/ramdisk/build.prop
8229 blocks
下面是上面 ramdisk 解压出来的目录结构
server :~/AOSP_T/out/target/product/board/tmpImage/init_boot_unpack_out/ramdiskStruct$ tree
.
├── debug_ramdisk
├── dev
├── first_stage_ramdisk
│ ├── debug_ramdisk
│ ├── dev
│ ├── metadata
│ ├── mnt
│ ├── proc
│ ├── second_stage_resources
│ └── sys
├── init
├── metadata
├── mnt
├── proc
├── second_stage_resources
├── sys
└── system
├── bin
│ └── snapuserd
└── etc
├── init
│ └── snapuserd.rc
└── ramdisk
└── build.prop
从目录结构中能看出,这个init位于ramdisk的根目录下,也就是第一阶段的 init 静态可执行程序。
最终 init_boot.img 会被烧写入 init_boot 分区。
编译规则如下
//system\core\init\Android.bp
cc_binary {
name: "init_first_stage",
stem: "init",
defaults: ["init_first_stage_defaults"],
...
srcs: [
...
"first_stage_main.cpp",
...
],
static_executable: true,
ramdisk: true,
install_in_root: true,
}
下面是编译时存放位置
server:~/AOSP_T/system/core/init$ mmm .:init_first_stage -j23
[100% 341/341] Install out/target/product/board/ramdisk/init
此处的 init 是由 linux kernel 启动的,它也是 kernel 的第一个用户程序,至于它是如何被 linux kernel 拉起来的则不在此处讨论。下面则是 first init 的入口方法
//system\core\init\first_stage_main.cpp
int main(int argc, char** argv)
return android::init::FirstStageMain(argc, argv);
//system\core\init\first_stage_init.cpp
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
...
至此 first init 则被启动了,即将开始它的任务。