OHOS 3.1的Init进程two_stages相关分析-1-编译部分 原创 精华
::: hljs-center
OHOS 3.1的Init进程two_stages相关分析-1-编译部分
:::
::: hljs-center
梁开祝 2022.05.04
:::
【注:本文可做为《沉浸式剖析OpenHarmony源代码》一书的第5章的5.4小节部分内容的大纲或草稿。】
OHOS LTS3.0版本的标准系统还不支持two_stages,3.1版本开始支持。这里的two_stages是指OHOS 3.1之后的标准系统,从内核态切换到用户态运行init进程时,分成两个stages来完成系统的启动工作:
- stage0运行在ramdisk中,主要是生成设备节点、挂载根文件系统,并切换到stage1去运行;
- stage1完成OHOS框架各模块、各进程的启动工作。
不过,OHOS 3.1标准系统烧录到HI3516DV300开发板,跑起来相当吃力,因此本文将基于DAYU200开发板,分别从编译和实现两大部分来对two_stages展开分析,最后再通过log确认一遍相关流程。
【本文很长,分两篇文章来发布:编译部分 和 实现部分】
1.编译部分
1.1 OHOS 3.1简明编译流程
请先去《OHOS3.1 简明编译流程》阅读和简单了解一下OHOS3.1系统的编译流程。
1.2 GN阶段与Ramdisk相关部分
在《OHOS3.1 简明编译流程》的“6.gn”步骤会执行“gn_gen”去预处理所有的.gn文件,生成对应的.ninja文件。其中与ramdisk相关的部分(局部),如下图1所示。
在//productdefine/common/device/rk3568.json文件里,定义了enable_ramdisk为true,它将会作为全局参数引入RK3568项目的编译流程中。
GN执行到//device/board/hihope/rk3568/BUILD.gn时,这里的group(“rk3568_group”)的deps关系中,就有对enable_ramdisk的判断和使用。其中的:
- “cfg:init_configs”:会拷贝fstab.required文件到//out/rk3568/目录下备用,也会把ramdisk_resource_config.ini文件拷贝到//out/rk3568/packages/phone/目录下备用。
注意,这里不再把ramdisk_resource_config.ini文件拷贝到//build/ohos/images/mkimage/目录下了,可以避免出现文章《OHOS3.1 cannot stat 'packages/phone/…/…/…/…/ramdisk.img》中描述的异常。 - “kernel:kernel”:里面的action(“kernel”)会在后面的内核编译阶段执行"build_kernel.sh"脚本,enable_ramdisk将作为其中一个参数参与编译内核。
- “updater:updater_files”:这一步会把会把updater_ramdisk_resource_config.ini文件拷贝到//out/rk3568/packages/phone/目录下备用。【后文暂不深入对updater_ramdisk_resource_config.ini进行分析】
在gn_gen阶段,//build/core/gn/BUILD.gn中还定义了group(“packages”)和group(“images”) ,其中的make_packages和make_images的动作,是在ninja的最后阶段去执行的,enable_ramdisk也作为重要的参数去生成烧录镜像,如下图2所示。
1.3 Ninja阶段与Ramdisk相关部分
在《OHOS3.1 简明编译流程》的“6.ninja”步骤会执行“ninja”程序,根据上一步生成的.ninja文件去生成所有的中间文件(.a/.o/.so/配置文件/可执行文件…)。
1.3.1 group(“rk3568_group”)
在执行到group(“rk3568_group”)时,会将fstab.required、ramdisk_resource_config.ini等文件拷贝到对应的目录备用。
1.3.2 action(“kernel”)
在执行到action(“kernel”)时,会执行build_kernel.sh去编译内核,并把resource.img、parameter.txt、MiniLoaderAll.bin、uboot.img、config.cfg等文件拷贝到//out/rk3568/packages/phone/images/中,注意:
if [ “enable_ramdisk” != “${6}” ]; then
cp ${KERNEL_OBJ_TMP_PATH}/boot_linux.img ${2}/boot_linux.img
fi
这里是不支持enable_ramdisk时,才会直接拷贝boot_linux.img;支持enable_ramdisk的话,这里先不拷贝,等后面group(“images”)阶段生成ramdisk.img时才会通过执行make-boot.sh,去重新生成boot_linux.img并拷贝到//out/rk3568/packages/phone/images/中。
如上图所示,前面5个文件都是在build_kernel.sh时拷贝到这里的;后面5个.img文件,除了boot_linux.img是在make-boot.sh生成并拷贝到这里之外,其余4个都是group(“images”)阶段执行build_image.py脚本生成并拷贝到这里的。
1.3.3 group(“packages”)
在执行到group(“packages”)时,其中一步会执行modules_install.py脚本,先删除//out/rk3568/packages/phone/目录下已存在的system、vendor、updater、ramdisk等目录,并重新生成它们。
此时注意看ramdisk和system子目录下的内容,用tree命令将其目录树结构打印出来,如下:
这里顺便把root、userdata、vendor、updater子目录的一级目录结构放上来做一下对比和参考。
上两图中,共计有三个init可执行程序:
- ramdisk子目录下的init(暂标记为initA)可执行程序
- system子目录下的init(暂标记为initB)可执行程序
- updater子目录下的init(暂标记为initA’)可执行程序
三者bit-to-bit的,你可以认为它们是同一个可执行程序的三份拷贝,它们都是由//base/startup/init_lite/目录下的代码编译出来的init可执行程序。
但是,从另外一个角度来看,initA、initB、initA’是三个完全不同的可执行程序!!!这个会在实现部分做详细说明。
1.3.4 group(“images”)
在执行到group(“images”)时,会执行build_image.py脚本去生成ramdisk.img、system.img、vendor.img、userdata.img镜像。
通过参数确定需要生成哪个image,先删除已经存在的image,再重新生成对应的子目录和link文件,执行mkimages.py去make具体的image。
mkimages.py会根据参数先加载config_file,即xxx_image_conf.txt文件,根据文件内的fs_type参数决定调用哪个工具(mkf2fsimage.py、mkextimage.py、mkcpioimage.py)去生成对应的image。xxx_image_conf.txt和dac.txt文件的使用说明,见同目录下的README.txt文件。
生成这些镜像的简单流程,可以参考1.2小节的图2的右半部分。
- 生成ramdisk.img
流程见1.2小节的图2的右半部分,分成三步:
[3-1] 根据ramdisk_resource_config.ini的描述,通过cpio工具将//out/rk3568/packages/phone/ramdisk/目录打包成//out/rk3568/ramdisk.img。
[3-2] 执行make-boot.sh,将//out/rk3568/ramdisk.img拷贝到//out/kernel/src_tmp/linux-5.10/boot_linux/extlinux/目录下,根据同目录下的extlinux.conf的描述,用mke2fs工具生成boot_linux.img,并拷贝到//out/rk3568/packages/phone/images/目录下。
[3-3] 支持two_stages时,这一步并不跑,直接return 0了。
这里生成的boot_linux.img镜像,我没有仔细研究镜像制作的细节,不大清楚img内部结构具体是什么样的,但大概估计一下,可能如下:
- 生成system.img
生成system.img,也可以参考1.2小节的图2的右半部分,具体流程图我就不画了。
mk_images()会先调用build_rootdir(src_dir),来把root目录和system目录拼接在一起,再调用mkextimage.py将它们制作成ext4格式的system.img。我没有仔细研究镜像制作的细节,不大清楚img内部结构具体是什么样的,但大概估计一下,可能如下:
生成其它的images的过程,请小伙伴们自行分析一下。
感谢大佬为OHOS 3.1开路,期待大佬接下来创作!