如何优雅地参与开源贡献,向顶级开源项目提交PR(Pull Request),跟着大咖30分钟成为OpenAtom OpenHarmony(简称“OpenHarmony”)Contributor。战“码”先锋直播间第五期,邀请华为终端BG OpenHarmony基础软件SIG/技术专家Handy为大家分享《OpenHarmony设备启动过程与模块化开发实践》。分享主要分为四个部分:OpenHarmony设备启动的基本过程,基于qemu平台的最小系统介绍,init进程的设计理念,以及如何基于qemu进行init的扩展模块开发。
● 第一部分,是从宏观上了解OpenHarmony在设备上的启动引导过程,了解操作系统启动引导的基本概念和相关术语。
● 第二部分,介绍基于qemu虚拟机平台的最小系统,如何在不要开发板的情况下进行OpenHarmony标准系统基础软件的开发。
● 第三部分,介绍OpenHarmony第一个用户态进程init的设计理念。
● 第四部分,介绍如何基于qemu虚拟机平台进行init的模块化开发。
1. 设备启动过程
1.1 OS启动引导技术概述
在介绍OpenHarmony操作系统启动引导过程前,Handy老师先回顾了传统PC行业操作系统的引导过程。上图是传统PC硬件和操作系统的大致结构,其中底层的是硬件主板,在主板上板载的firmware将完成主板的自启;然后扫描存储设备,包括硬盘、光盘、U盘等;再从存储设备上识别已安装的操作系统,最终从这些操作系统上启动。
在PC环境下,firmware都遵循UEFI标准。UEFI是一个非常复杂的标准,由CPU厂商,PC主板厂商和OS厂商联合开发,主要包括Win-Tel。该标准详细定义了固件和操作系统之间的接口,适应了PC硬件的开放式架构,使得不同的操作系统都可以在各个不同厂商的CPU、主板、硬盘、内存上运行。UEFI标准的实现包括EDK2、coreboot、LinuxBoot等。
但在嵌入式系统中,这些标准则相对简化。因为嵌入式设备不像早期PC一样可以任意组装。嵌入式设备就像一体机,SOC、RAM、EMMC、外设以及操作系统等都是在设备出厂时预制好,消费者开箱即用。因此,SOC板载的firmware一般相对简化,只需要加载到bootloader,操作系统开发人员基本不关心SOC的firmware。
Bootloader是操作系统的直接上游,操作系统需要由Bootloader来加载并运行。在嵌入式系统中,一般都采用uboot。在uboot中可以指定操作系统镜像在存储器中的具体位置,这次主要基于u-boot介绍OpenHarmony标准系统的启动引导过程。
另外还有两个基本概念:分区表和OS镜像。分区表是用来把存储器的存储区域进行划分,不同区域存放不同的OS镜像。
1.2 OpenHarmony启动引导分区加载过程
上图为我们指明了OpenHarmony相关的OS镜像。u-boot首先加载boot.img和ramdisk.img。boot.img是内核镜像,ramdisk.img是最早的用户态进程镜像,其中就包括init进程。通过这两个OS镜像,系统可以启动到最基本的shell,这里还没有启动任何业务。
在ramdisk.img的init进程里,会主动挂载system.img和vendor.img,并扫描其中的启动配置文件,拉起各个进程。system.img和vendor.img是OpenHarmony中各个子系统编译后产物的集合。
从上图右侧文字我们可以看到,u-boot和OpenHarmony镜像启动时都需要知道分区表信息。分区表信息有多种方式传递,一般包括GPT分区表,bootargs分区表。图中示意的是u-boot通过blkdevparts这个bootargs传递给内核。内核会根据这些信息创建对应的block设备。同时还有root这个节点,告知内核从哪里挂载根文件系统,从而启动init。
ramdisk里的init最重要的几个事件包括:创建并挂载根文件系统,包括tmpfs、dev节点、procfs等。同时,需要挂载system.img和vendor.img,这两个是启动过程的必选分区。当前Release版本里是通过ramdisk.img里的required.fstab文件来配置system、vendor分区的挂载参数;最新master版本还支持通过ohos.required_mount.xxx bootargs参数来提供这些挂载参数;具体参考文档可以参考《启动子系统概述》(https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-overview.md)。
ramdisk里的init完成system/vendor的挂载后,就开始进入system/vendor系统中,开始第二阶段并发启动的过程。此时,init会扫描/{system,vendor}/etc/init下的各个启动配置文件,拉起各个子系统的服务,并最终拉起应用。在分区挂载方面,还有一个重要的配置文件/vendor/etc/fstab.{hardware};这个可以定义更多需要挂载的分区,包括data分区,以及产品扩展的分区。
1.3 OpenHarmony系统进程启动过程
随后,Handy老师为我们介绍了进入OpenHarmony系统后,用户态进程的启动概况。从上图中,我们可以把启动的进程分为以下几类:
● UHDF类系统进程UHDF类系统进程为系统提供HDI接口,这类进程为系统服务提供芯片无关的硬件访问接口。这类进程都通过hdf_devmgr管理。
● SA类系统进程SA是OpenHarmony的基础系统元能力,每个SA是一个独立的so,根据配置一个或多个SA可以部署到同一个进程中,我们称这类进程为SA类系统服务。每个SA类系统服务进程都是通过sa_main进程解析配置文件启动,向sa_mgr服务注册支持的SA;访问SA服务时需要先根据SA的ID向sa_mgr获取该SA的句柄。
● Linux原生系统服务OpenHarmony除了支持SA类和UHDF类系统进程外,也支持启动Linux原生的系统进程。通过Linux原生系统服务可以快速使用Linux社区已有的成熟能力。
● 应用进程每个应用进程都是从appspawn孵化而来,appspawn预加载了应用运行时需要的资源,主要是ArkUI相关的依赖库。
init拉起每个进程的方式都是通过配置文件来完成,其格式都是如下所示的JSON格式;每个进程的配置文件安装到/system/etc/init或/vendor/etc/init目录下,init会扫描这些配置,按照配置拉起对应的进程。下面我们将结合qemu最小系统来介绍下init的详细设计。
{
"services" : [{
"name" : "watchdog_service",
"start-mode" : "condition",
"path" : ["/system/bin/watchdog_service", "10", "2"],
"disabled" : 1,
"sandbox" : 0,
"uid" : "watchdog",
"gid" : ["watchdog", "log", "readproc"],
"secon" : "uwatchdog_service:s0"
}
]
}
2. 基于qemu的最小系统
2.1 Why qemu
硬件设备开发人员在开发工作中,需要使用到各种各样的开发板。每个开发板的连接线缆、接线方式、升级烧写方式各不相同,且上手门槛高;开发时的便携性和调试效率等都比较低。特别是init相关的开发调试,修改后还需要整机烧写。为了能像应用开发者一样,可以随时随地,相对高效且“体面”地开发底层系统服务。于是,构建了基于qemu的OpenHarmony最小系统,希望能让硬件设备开发人员只需一台笔记本就可以随时开发调试底层系统服务。2.2 关于qemu-arm-linux-min
OpenHarmony的qemu最小系统名称是qemu-arm-linux-min。从名称可以看出,它是用qemu模拟的ARM32位运行平台,使用Linux内核运行的OpenHarmony最小系统部件集合。其部件集合的定义在vendor/ohemu/qemu_arm_linux_min/config.json里,包含约20个部件,主要是系统基础的启动、DFX、安全、samgr、软总线相关的部件。
编译命令只需要指定qemu-arm-linux-min产品名即可,运行也只需要一个qemu-run.sh命令。详细的信息可以跳转到文末的device/qemu/arm_virt虚拟平台的文档。
qemu-arm-linux-min的优势:
● 代码仓少,只需要96个仓代码(-g ohos:chipset -m chipsets/qemu.xml),详细说明参考https://gitee.com/openharmony/manifest。
● 编译快:只需要编译5000个文件(完整系统需3万个)。
● 免烧写:qemu-run.sh直接运行。
因此,开发者仅需一台笔记本,就可以随时随地写代码,轻松为OpenHarmony做贡献。
2.3 DEMO TIME
了解qemu-arm-linux-min介绍后,Handy老师为我们介绍了如何使用它。
arm_virt网页上已经比较详细地介绍了运行虚拟机的准备工作了。前面编译环境准备以及下载代码的都是通用的,编译命令前面也说明了,只需要指定qemu-arm-linux-min即可。运行前,需要先安装qemu,请下载5.2以上版本的qemu,并对源码进行编译。
qemu-run.sh运行脚本有两个运行模式,普通模式直接启动,虚拟机只有虚拟磁盘,没有网络。-n选项可以创建虚拟网桥,使得虚拟机和主机之间可以通过网络通信,使用hdc等命令。下面我们演示如何使用qemu-arm-linux-min进行gdb调试。
调试环境如下图所示:主机上通过qemu-run.sh创建了虚拟网桥,用于与虚拟机通信。同时,为了在虚拟机上访问源码进行gdb调试,在主机上启动了smbd服务。虚拟机的内核默认开启了cifs模块,可以挂载主机上的smb共享目录。
● 使能虚拟机的网络接口:
# 使能虚拟机网络接口
ifconfig eth0 192.168.100.2
# 测试与主机侧的网络连接
ping192.168.100.1-t4
● 在虚拟机挂载主机的samba共享目录:
● 使用gdb:# 创建挂载点
mkdir /mnt/smb
# 挂载cifs文件系统
mount -t cifs -o username=xxx,password=xxx,vers=2.1
//192.168.100.1/handy /mnt/smb
# 可选建立hdc连接
hdc_stdtconn192.168.100.2:5555
/mnt/smb/tools/gdb /mnt/smb/ohos/out/qemu-arm-linux/exe.unstripped/startup/init/gdbtest
directory /mnt/smb/ohos/out/qemu-arm-linux
arm版的gdb可以从以下网站获取:
https://github.com/therealsaumil/static-arm-bins/(需解决网络问题)
https://gitee.com/stesen/ohos_cross_tools
3. init进程的设计理念
3.1 init进程的模块划分
通过前文的介绍,可以知道init进程是系统从内核态向用户态引导的核心进程;该进程是所有用户态进程的父进程。
init的模块划分如上图所示,启动过程大体分为第一阶段和第二阶段。第一阶段用于创建基础的根文件系统,包括procfs、sysfs、dev设备节点、tmpfs等。第二阶段提供了系统参数服务,服务脚本解析能力;然后就进入了脚本配置启动的过程。
具体配置参考《init启动引导组件》(https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init.md)。
这里很重要的部分是init里提供了模块化引擎,提供了扩展模块开发的对外API,可以在不改变init框架的基础上扩展init各个模块的功能。例如可以扩展脚本配置的命令,扩展服务管理功能,在脚本运行前扩展钩子执行等。
3.2 init进程的启动顺序与扩展机制说明
上图是init进程启动的详细过程,主要分为三个部分:
● 第一阶段如前面描述,完成基础根文件系统的构建。
● 第二大部分提供了系统参数服务,并且完成了配置脚本的扫描与解析。
● 第三大部分进入了脚本化运行的阶段。
第一部分逻辑固定,不提供扩展;第二部分都是native代码,可以通过开发扩展模块向红色扩展点注册钩子函数来扩展功能。第三部分通过配置脚本进行扩展,每个系统服务都可以编写各自的配置文件在指定阶段完成相应功能。
3.3 init脚本化启动过程说明
脚本化启动过程大体可以分为三个阶段:
● pre-init完成脚本化早期工作,包括ueventd、data分区挂载等。
● init阶段完成samgr和hdf_devmgr的启动,这两个进程是各个SA进程以及HDI服务进程的管理中心,公共依赖需提前启动。
● post-init阶段是各个子系统服务启动的阶段。为了保障整机开机启动速度,这个阶段各个服务都是并行启动的,服务之间如果有依赖关系,需要进行运行时同步设计。init提供了系统参数服务,可以提供wait和watch机制,辅助各个服务进行同步。
4. init扩展模块开发示例
init扩展模块代码都放在base/startup/init_lite/services/modules目录下,代码引用API头文件定义及插件代码入口:BUILD.gn编译脚本依赖及插件安装目录:
MODULE_CONSTRUCTOR(void)
{
// 加载插件代码入口,dlopen此插件库时自动执行
}
MODULE_DESTRUCTOR(void)
{
// 卸载插件代码入口,dlclose此插件库时自动执行
}
OpenHarmony期待你的加入,与Handy老师一起,深入理解OpenHarmony系统启动,提PR,轻松踏上设备软件开发之旅,成为贡献达人,为OpenHarmony生态发展贡献力量。ohos_shared_library("libinit_example_module") {
...
external_deps = [ "init:libinit_module_engine" ]
module_install_dir = "lib/init/"
...
}
附录:
启动恢复子系统概述:
https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-overview.md
qemu ARM Virt 标准系统教程:
https://gitee.com/openharmony/device_qemu/tree/master/arm_virt/linux
qemu-arm-linux-min代码仓说明:
https://gitee.com/openharmony/manifest
qemu ARM Virt 标准系统教程:
https://gitee.com/openharmony/device_qemu/tree/master/arm_virt/linux
Arm版的gdb可以从以下网站获取:
https://github.com/therealsaumil/static-arm-bins/
https://gitee.com/stesen/ohos_cross_tools
init启动引导组件:
https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init.md
审核编辑 :李倩
-
开源
+关注
关注
3文章
3235浏览量
42358 -
模块化
+关注
关注
0文章
328浏览量
21323 -
OpenHarmony
+关注
关注
25文章
3649浏览量
16089
原文标题:30分钟成为Contributor|深入理解OpenHarmony系统启动 轻松踏上设备软件开发之旅
文章出处:【微信号:gh_e4f28cfa3159,微信公众号:OpenAtom OpenHarmony】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论