一、启动概述
在产品代码成功编译通过后,开始进行下一步的运行调测阶段,而运行调测第一步便需要了解系统的启动过程。对于 OpenHarmony 来说,系统启动流程如下:
---> uboot启动
---> uboot启动内核
---> 内核挂载根文件系统(此时为ramdisk文件系统)
---> 运行ramdisk中的第一个程序
---> 根据fstab中内容挂载文件系统
---> 切换root路径为/usr
---> 第一个程序为init则进行系统初始化
---> 第一个程序为init_early则通过execv启动init
关于 uboot 启动到内核挂载根文件系统部分属于 Linux 内容,这里不做介绍,以下我们开始来介绍从 ramdisk 启动的第一个程序,我们以 init_early 模式为例开启我们新的篇章
二、ramdisk 文件系统介绍
2.1 什么是 ramdisk 文件系统
ramdisk 是一种将内存中的的一块区域作为物理磁盘来使用的一种技术,也可以说,ramdisk 是在一块内存区 域中创建的块设备,用于存放文件系统。对于用户来说,可以把 ramdisk 与通常的硬盘分区同等对待来使用。ramdisk 不适合作为长期保存文件的介质,掉电后 ramdisk 的内容会消失。
2.2 ramdisk 文件系统和 ramdisk.img 有什么关系
在 Linux 中,根文件系统是需要挂载到实际的物理磁盘中的,而 ramdisk.img 便是 ramdisk 文件系统挂载的磁盘,即 ramdisk.img 是 ramdisk 文件系统的打包镜像。
可以对比 rootfs,我们通过 busybox 制作出来的是 rootfs 文件系统,但是实际启动使用的时候我们时我们需要将 rootfs 文件系统打包制作成 rootfs.ext4 一样。
三、init_early 程序介绍
3.1 init_early 程序注意事项
init_early 程序作为第一个启动的程序,由于当前挂载的文件系统为 ramdisk 文件系统,该系统的目的仅仅是为了拉起 OpenHarmony 真正的文件系统,可以说仅仅是为了 init_early 程序的运行,因此内部的库很少,仅有以下内容,所以 init_early 程序仅可以依赖以下这些库
wen_fei@rh-Z790-UD:~/OpenHarmony/dayu800-v4.1-release/out/dayu800/packages/phone/ramdisk/lib64
$ tree
.
├── chipset-pub-sdk
│ ├── libpcre2.z.so
│ ├── libsec_shared.z.so
│ └── libselinux.z.so
├── libclang_rt.asan.so
├── libc++.so
├── libc.so
├── libinit_module_engine.so -> libinit_stub_empty.so
├── libinit_stub_empty.so
├── libload_policy.z.so
└── platformsdk
└── librestorecon.z.so
3.2 为什么要有 init_early 程序
作为第一个基于 ramdisk 文件系统启动的程序,能够依赖的库有限,因此能实现的功能相对也不能复杂,通过使用 init_early 拉起 init 进程可以在尽可能减小 ramdisk.img 大小的同时很好的让 init 程序开发更加丰富的内容。
其次如果 init 程序加载有问题也可以通过 init_early 程序先启动到 shell,然后在 shell 中运行 init 进行调测。
以上内容均为个人猜想。
3.3 init_early 代码路径
该部分代码的编译参考:base/startup/init/services/init/standard/BUILD.gn
其 main 函数位于:base/startup/init/services/init/standard/main_early.c
3.4 init_early 代码介绍
从其 main_early.c 代码中可以看出 init_early 主要完成以下几个功能
-
忽略终端信号,将 SIGPIPE 交给系统处理
-
使能 InitLog 的 INIT_INFO 级别(非核心)
-
初始化 EarlyLog(非核心)
-
创建常用的文件和设备节点
-
执行钩子函数,一般钩子链表是通过__attribute__((constructor))构造的函数添加的
-
确实是否为升级模式
-
根据 ramdisk 镜像中的 fstab 文件挂载镜像
-
启动第二阶段 init
- 关闭 stdio(此时便不能通过 printf 打印 log)
- 切换 root 路径为/usr(system 文件系统)
- 让 init 程序代码当前的 init_early 程序进行
注意这里是程序不是进程,因为 init_early 在 ramdisk 中是软链接为 init,因此进程对应的是 init,而不是 init_early
四、init 启动介绍
4.1 init 运行前准备工作
由于 init_early 的铺垫,此时 init 启动的实际文件系统已经不在 ramdisk 文件系统中了,而是位于 system 文件系统中。因此链接库的路径指定是通过 etc/ld-musl-namespace-riscv64.ini 该文件中设置的路径按照顺序链接的,所以首先必须确定 system 镜像中是否有该文件。
在 init 程序中有很多函数通过 MODULE_CONSTRUCTOR 将其添加到了 Hook 链表中,在 init 实际运行的时候会调用 HOOK 的执行接口,将所有的预处理函数调用执行。
4.2 init 启动失败调测
如果 init_early 加载 init 程序运行直接失败,我们可以在 init_early 最后添加如下代码后让串口进入 shell,然后在 shell 中直接运行 init 跟踪定位
execv("/bin/sh", NULL);
4.3 init 启动的流程
这部分就通过 init 的 main 函数进行阅读理解了,注意 HOOK 链表项都是通过 MODULE_CONSTRUCTOR 接口在 main 函数执行前添加的,详细请了解 gcc 的 __attribute__((constructor))
属性
init 的 main 函数位于:base/startup/init/services/init/main.c
最后
如果你想成为一名鸿蒙开发者,以下这些资料将是十分优质且有价值,让你的鸿蒙开发之路事半功倍!相对于网上那些碎片化的知识内容,这份学习资料的知识点更加系统化,更容易理解和记忆。
鸿蒙Next全套VIP学习资料←点击领取!(安全链接,放心点击)
包含了:【OpenHarmony多媒体技术、Stage模型、ArkUI多端部署、分布式应用开发、音频、视频、WebGL、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。
1.鸿蒙(HarmonyOS NEXT)最新学习路线
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。获取以上完整
版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
2.大厂面试必问面试题
3.鸿蒙南向开发技术
4.鸿蒙APP开发必备
5.HarmonyOS Next 最新全套视频教程
6.鸿蒙生态应用开发白皮书V2.0PDF
获取以上完整鸿蒙HarmonyOS学习资料,请点击→
纯血版全套鸿蒙HarmonyOS学习资料
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地