鸿蒙 OS 开源代码精要解读之——init
作者介绍:
中科创达 OpenHarmony 研究组
阐明:
中科创达 OpenHarmony 研究组第一工夫对 https://codechina.csdn.net/op…。为此,咱们打算编写一系列篇幅中等,内容精炼的源码剖析文章来引领大家更进一步的走进鸿蒙 OS。随着对代码的理解,宽广开发者想亲自动手参加的志愿和信念也会随之加强——这也是鸿蒙 OS 开源的意义所在。
本篇内容摘要:
本篇以 OpenHarmony 中 ipcamera_hi3518ev300 为编译指标,介绍 init 过程的相干代码。
写在后面的话
咱们对 OpenHarmony 的代码进行了一个简略粗略的统计。除去所有的 third_party 代码(即 OpenHarmony 应用的第三方开源库),其余残余的代码中,以.c、.h 文件为统计入口,总无效代码行数(不含正文、空行等,统计工具为 tSourceCounter)为 325627 行。其中,归属 kernel 目录下的总无效代码行数为 74150 行。整个 OpenHarmony 中,kernel 局部占比为 22.8% 左右,代码量上占大头的还在于 kernel 之上的、咱们称之为 Framework 的局部。依据咱们在 Android 零碎上多年的摸索和教训,Framework 恰好是 Android OS 的精华。所以,以 OpenHarmony 目前才 20 多万行的 Framework 代码量来看,感兴趣的开发者在这块参加共建、献策献力的机会十分大。
1. OpenHarmony 源码的下载和编译
先介绍代码的下载和编译。咱们研究组用得是 ubuntu 19.10 的主机环境。
1.1 源码下载
依照 codechina.csdn 官网的源码下载指南:https://codechina.csdn.net/op…
咱们应用的是第四种形式“获取形式 4:从代码仓库获取”。执行这一节中的几个命令,即可失去整个源码仓库。
1.2 编译源码
咱们抉择的编译指标是“Hi3518 解决方案”, 其编译后的输入目录名为 ipcamera_hi3518ev300。ipcamera_hi3518ev300 是一个基于海思的 ip 摄像头设施。相干的介绍文档入口在 https://codechina.csdn.net/op…。
留神,编译不同的解决方案须要建设对应的编译环境。对 hi3518 来说,开发者须要依照上述链接里的“搭建环境”来下载和配置。
所有就绪后,在源码根目录下执行 python build.py。如果不带参数的话,它会揭示你指定编译指标,截图如下:
这次,咱们通过 python build.py ipcamera_hi3518ev300 即可编译“Hi3518 解决方案”。编译耗时 10 几分钟。
留神,编译过程中可能呈现找不到 <valgrind/valgrind.h> 的谬误。这是因为目前咱们下载的代码中没有蕴含 valgrind 的头文件。开发者能够手动将 /usr/include/valgrind 目录拷贝到 prebuilts/lite/sysroot/usr/include 下即可(仅限 Ubuntu 平台,需提前装置好 valgrind 工具)。
1.3 OpenHarmony 编译相干小常识介绍
OpenHarmony 源码编译系统应用了 google 开发的 gn 工具以及 ninjia。这二者联合起来比传统的 makefile 编译系要高效,尤其适宜大零碎的并行编译。对开发者而言,如果要参加 OpenHarmony 的开发,须要对 gn 的语法有些理解。本文仅做一些最根本的介绍:
- 应用 gn 工具的话,开发者将编译规定写在名为 BUILD.gn 文件中。和 Makefile 一样,gn 文件有本人的语法规定,属于畛域语言(Domain Specific Language,DSL)。gn 语法不难,但编译规定自身有很多内容,所以一下子要把握全部内容也不容易。
- gn 反对自定义模板函数,可放在名为.gni 的文件中。OpenHarmony 中最常见到的 gn 模板文件为./build/lite/config/component/lite_component.gni。.gn 文件中通过 import 可导入 gni 模板文件。OpenHarmony 定义了 lite_component、lite_library 等模板函数。
- gn 中,可执行文件的编译函数入口为 exectuable(“ 文件名 ”),共享库的编译规定函数为 shared_library(“ 文件名 ”)。所以,如果要搜寻某个文件对应的编译规定,能够先搜寻所有的 BUILD.gn 文件,而后 grep executable。以下是咱们 grep 所有的 executable 的后果截图。
通过这种形式,咱们能很快定位到比方 init 对应的代码在什么中央。
最初,咱们再简略介绍下 OpenHarmony 编译系统中和底层 OS 无关的一个条件编译控制变量 ohos_kernel_type。目前,该变量有四个取值,别离为 ”liteos_a”、”liteos_m”、”liteos_riscv” 和 ”linux”:
- “liteos_a” 和 ”linux” 常常做为一组进行判断。liteos_a 理论对应的是 Cortex- A 系列,其性能绝对较高,能够跑 Linux 零碎。
- “liteos_m” 和 ”liteos_riscv” 往往是一组的。liteos_m 对应的是 Cortex- M 系列,liteos_riscv 是 Riscv 芯片的示意,二者可能都是针对性能个别,功耗较低的设施。
ohos_kernel_type 的取值由 build/lite/product/ 解决方案名.json 文件中的 product 字段决定。例如,咱们抉择的 ipcamera_hi3518ev300 的配置文件内容截图如下,它的 kernel 字段值为 ”liteos_a”。
编译实现后,所有编译生成物都在 out/ipcamera_hi3518ev300 目录下。
2 init 源码精要解析
init 是 Linux 零碎上的第一个利用过程,是其它过程的源头。对 ipcamera_hi3518ev300 来说,它的编译产物中也有一个 init 过程。
在下面提到的 out/ipcamera_hi3518ev300 目录下,有一个 rootfs.tar 文件。这个文件里就是设施上根文件系统的内容。关上其中的 /rootfs/bin 目录,能够看到此次编译的可执行程序如下截图所示:
借助图 2 里提到的方法,咱们能够定位到 init 对应的代码门路为 base/startup/services/init_lite/。其内容如下图所示:
main.c 是整个 init 的入口。咱们简略看一下它的代码,如下所示。
init main 函数十分精简,十分合乎 ”lite” 轻量简便的格调。当然,也不排除将来 init 的代码会越来越简单。咱们在 AOSP 上察看到的状况就是一个例子——AOSP 里当初的 init 的相干代码非常复杂)。
咱们对 InitReadCfg 比拟感兴趣,这个函数外部将读取 /etc/init.cfg 文件。这个文件在图 4 中提到的 rootfs.tar 中能够找到,下图是其内容的示意:
init.cfg 实质上是一个 json 格局的文件。它包含一个名为 ”jobs” 的数组和一个名为 ”services” 的数组。
- 对 ”jobs” 来说:外部别离蕴含 ”pre-init”、”init” 和 ”post-init” 三个元素。从下面的截图中能够看出,这三个元素对应的就是设置挂载一些设施、设置好门路,启动服务等工作。
- 对 ”services” 来说:它蕴含一组服务的定义。所谓的服务,就是零碎里的要害过程。能够猜测到,init 将依据 service 的配置来启动对应的服务程序,并设置它的 uid、gid、过程优先级和权限等。
如果开发者对 Android 零碎有肯定理解的话,会发现 OpenHarmony 和 AOSP 在 init 的工作流程上有着类似的设计思路。不过,对 OpenHarmony 指标设施来说,应用 json 格局无疑是比较简单且不便的。
最初,咱们再看一下 init 的另外一个重要职能——服务过程情况监控。init.cfg 中的那些服务属于零碎要害过程。运行过程中如果它们出现异常导致过程退出,须要有个方法将它们重新启动以保障业务连续性。
这个性能的实现就是利用 Linux 零碎的 SIGCHILD 信号。init 在 SignalInitModule 中监听了该信号并设置了对应的信号处理函数——SigHandler。SigHandler 函数的具体处理过程则比此处说得要更简单一点。当初,这部分内容就留给读者们自行摸索了!!
原文链接:https://developer.huawei.com/consumer/cn/forum/topicview?tid=0202366642839450045&fid=0101303901040230869
作者:innost