鸿蒙OS开源代码精要解读之——init

鸿蒙OS开源代码精要解读之——init

做者介绍:python

中科创达OpenHarmony研究组linux

说明:json

中科创达OpenHarmony研究组第一时间对https://codechina.csdn.net/openharmony上开源的代码进行了详尽的代码研读和学习。为此,咱们打算编写一系列篇幅中等,内容精炼的源码分析文章来引领你们更进一步的走进鸿蒙OS。随着对代码的了解,广大开发者想亲自动手参与的意愿和信心也会随之加强——这也是鸿蒙OS开源的意义所在。ubuntu

本篇内容摘要:数组

本篇以OpenHarmony中ipcamera_hi3518ev300为编译目标,介绍init进程的相关代码。ide

写在前面的话

咱们对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 源码下载post

按照codechina.csdn官网的源码下载指南:https://codechina.csdn.net/openharmony/docs/-/blob/master/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md

咱们使用的是第四种方式“获取方式4:从代码仓库获取”。执行这一节中的几个命令,便可获得整个源码仓库。

1.2 编译源码

咱们选择的编译目标是“Hi3518解决方案”,其编译后的输出目录名为ipcamera_hi3518ev300。ipcamera_hi3518ev300是一个基于海思的ip摄像头设备。相关的介绍文档入口在https://codechina.csdn.net/openharmony/docs/-/blob/master/quick-start/%E6%90%AD%E5%BB%BA%E7%8E%AF%E5%A2%83-2.md。

注意,编译不一样的解决方案须要创建对应的编译环境。对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的语法有些了解。本文仅作一些最基本的介绍:

  1. 使用gn工具的话,开发者将编译规则写在名为BUILD.gn文件中。和Makefile同样,gn文件有本身的语法规则,属于领域语言(Domain Specific Language,DSL)。gn语法不难,但编译规则自己有不少内容,因此一会儿要掌握所有内容也不容易。

  2. gn支持自定义模板函数,可放在名为.gni的文件中。OpenHarmony中最多见到的gn模板文件为./build/lite/config/component/lite_component.gni。.gn文件中经过import可导入gni模板文件。OpenHarmony定义了lite_component、lite_library等模板函数。

  3. gn中,可执行文件的编译函数入口为exectuable("文件名"),共享库的编译规则函数为shared_library("文件名")。因此,若是要搜索某个文件对应的编译规则,能够先搜索全部的BUILD.gn文件,而后grep executable。如下是咱们grep全部的executable的结果截图。
    在这里插入图片描述

经过这种方式,咱们能很快定位到好比init对应的代码在什么地方。

最后,咱们再简单介绍下OpenHarmony编译系统中和底层OS有关的一个条件编译控制变量ohos_kernel_type。目前,该变量有四个取值,分别为"liteos_a"、"liteos_m"、"liteos_riscv"和"linux":

  1. "liteos_a"和"linux"常常作为一组进行判断。liteos_a实际对应的是Cortex-A系列,其性能相对较高,能够跑Linux系统。

  2. "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"的数组。

  1. 对"jobs"来讲:内部分别包含"pre-init"、"init"和"post-init"三个元素。从上面的截图中能够看出,这三个元素对应的就是设置挂载一些设备、设置好路径,启动服务等工做。

  2. 对"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

相关文章
相关标签/搜索