【鸿蒙OS开发入门】11 - 启动流程代码分析的第一个用户态过程:init 进程 之 Services简介
-
- 一、系统默认Services:ueventd、console、hdcd
-
- 1.1 ueventd 监控设备节点
- 1.2 console 用户登录终端处理程序
- 1.3 hdcd 命令行处理工具的守护过程相当于android的 adb
- 二、各模块Services简介
-
- 2.1 accountmgr.cfg 系统帐号组件
- 2.2 appspawn.cfg 孵化器组件的应用
- 2.3 audio_policy.cfg 音频组件
- 2.4 camera_service.cfg 相机组件
- 2.5 deviceauth_service.cfg 设备认证模块
- 2.6 distributed_data.cfg 分布式数据服务
- 2.7 distributedpermission_service.cfg 分布式权限管理
- 2.8 distributedsched.cfg 布式任务调度模块 dmsfwk
- 2.9 faultloggerd32 临时日志管理模块崩溃
- 2.10 foundation.cfg 用户程序框架子系统 samgr
- 2.11 graphic.cfg 图形子系统
- 2.12 hdf_devmgr.cfg 用户态驱动子系统
- 2.13 hilogd.cfg 日志文件系统
- 2.14 hiview.cfg 跨平台终端设备维护服务集
- 2.15 huks_service.cfg 鸿蒙通用密钥库系统
- 2.16 inputmethodservice.cfg 输入法框架
- 2.17 installs.cfg 管理服务框架
- 2.18 lmks.cfg 用户程序管理服务框架
- 2.19 media_service.cfg 媒体组件
- 2.20 medialibrary_service.cfg 媒体库组件
- 2.21 pulseaudio.cfg 音频组件
- 2.22 softbus_server.cfg 布式软总线组件
- 2.23 telephony.cfg 核心电话服务模块
- 2.24 timeservice.cfg 时间组件
- 2.25 updater_sa.cfg 升级服务组件
- 2.26 weston.cfg 图形子系统Wayland
- 2.27 wifi_standard.cfg 无线局域网组件
- 2.28 bluetooth_service.cfg 启动蓝牙服务
本系列文章总结:
- 《【鸿蒙OS开发入门】01 - 搭建Ubuntu虚拟机开发环境
- 《【鸿蒙OS开发入门】02 - 启动流程代码分析Uboot 第一阶段:解压引导加载u-boot.bin》
- 《【鸿蒙OS开发入门】03 - 启动流程代码分析Uboot 第二阶段:之board_init初始化》
- 《【鸿蒙OS开发入门】04 - 启动流程代码分析Uboot 第二阶段:之U_BOOT_CMD原理》
- 《【鸿蒙OS开发入门】05 - 启动流程代码分析Uboot 第二阶段:之bootm引导加载Kernel OS》
- 《【鸿蒙OS开发入门】06 - 启动流程代码分析KernelOS:之启动Linux-4.19 Kernel内核》
- 《【鸿蒙OS开发入门】07 - 安装docker环境编译openharmony 2.0代码》
- 《【鸿蒙OS开发入门】08 - 启动流程代码分析KernelOS:之启动 liteos_a 内核》
- 《【鸿蒙OS开发入门】09 - 启动流程代码分析KernelOS:之启动Linux-4.19 Kernel内核 中do_basic_setup()大事
- 《【鸿蒙OS开发入门】10 - 启动流程代码分析的第一个用户态过程:init 进程》
- 《【鸿蒙OS开发入门】11 - 启动流程代码分析的第一个用户态过程:init 进程 之 Services简介》
- 《【鸿蒙OS开发入门】12 - 启动流程代码分析的第一个用户态过程:init 进程 之 pre-init 任务详解》
- 《【鸿蒙OS开发入门】13 - 启动流程代码分析的第一个用户态过程:init 进程 之 init 任务详解》
- 《【鸿蒙OS开发入门】14 - 启动流程代码分析的第一个用户态过程:init 进程 之 post-init 任务详解》
- 《【鸿蒙OS开发入门】15 - 启动流程代码分析的第一个用户态过程:init 进程 之 libuv 做了啥?》
我们前面分析过,init进程中:
# base\startup\init_lite\services\src\main.c int main(int argc, char **argv) {
...... // 4. 分别执行pre-init、init、post-init 等待相关事项 InitReadCfg(); ---------> ParseInitCfg(INIT_CONFIGURATION_FILE); // "/etc/init.cfg"
DumpAllServices
(
)
;
// 打印所有的服务信息,系统中所有现有的服务保存在 static Service* g_services 中,通过g_servicesCnt来进行索引计数。
+
DoJob
(
"pre-init"
)
;
// 执行 `/etc/init.cfg` 中 `pre-init`的内容
+
DoJob
(
"init"
)
;
// 执行 `/etc/init.cfg` 中 `init`的内容
+
DoJob
(
"post-init"
)
;
// 执行 `/etc/init.cfg` 中 `post-init`的内容
+
ReleaseAllJobs
(
)
;
// 释放init.cfg中所有的jobs 命令所占用的空间
<
--
--
--
--
-
.
.
.
.
.
.
}
其中,在 ParseInitCfg("/etc/init.cfg")
中,实现对 init.cfg
中所有的 services
的解析, 并保存在g_services
中,g_servicesCnt
是统计所有services
的计数。
# base\startup\init_lite\services\src\init_read_cfg.c
static void ParseInitCfgContents(const cJSON *root)
{
// parse services
ParseAllServices(root);
=============>
+ Service* retServices = (Service*)realloc(g_services, sizeof(Service) * (g_servicesCnt + servArrSize));
+ for (int i = 0; i < servArrSize; ++i) {
+ cJSON* curItem = cJSON_GetArrayItem(serviceArr, i);
+ int ret = ParseOneService(curItem, &tmp[i]);
+ GetServiceOnRestart(curItem, &tmp[i]); // 解析服务OnRestart的命令
+ }
+ RegisterServices(retServices, servArrSize); // 注册所有的服务,实际就是简单的指针赋值 g_services=retServices。
+ ------>
+ - g_services = services;
+ - g_servicesCnt += servicesCnt;
+ <------
<============
ParseAllJobs(root);
// parse imports
ParseAllImports(root);
}
那,本文,我们就来罗列下,在鸿蒙OS 3.0,有哪些Services呢? 本文主要是简单对一些重要的Services 进行分析下,看看这些Services在系统中扮演什么角色
一、系统默认的Services:ueventd、console、hdcd
遍历代码中的所有json配置文件:
"/base/startup/init_lite/services/etc/init.cfg"
"/base/startup/init_lite/services//etc/init.usb.cfg",
"/base/startup/init_lite/services//etc/init.usb.configfs.cfg",
"/base/startup/init_lite/services//etc/init.usb.cfg",
"/device/hisilicon/hi3516dv300/build/rootfs/init.Hi3516DV300.usb.cfg",
"/device/hisilicon/hi3516dv300/build/rootfs/init.Hi3516DV300.cfg"
找到如下几个Service
:ueventd
、console
、hdcd
# base\startup\init_lite\services\etc\init.cfg
"services" : [
{
"name" : "ueventd",
"path" : ["/system/bin/ueventd"],
"critical" : 1
},
{
"name" : "console",
"path" : ["/system/bin/sh"],
"disabled" : 1,
"console" : 1,
"uid" : "root",
"gid" : ["shell", "log", "readproc"]
}
]
# base\startup\init_lite\services\etc\init.usb.cfg
"services" : [
{
"name" : "hdcd",
"path" : ["/system/bin/hdcd"],
"socket" : [
"hdcd seqpacket 660 system system false"
],
"disabled" : 1
}
]
1.1 ueventd 设备节点监控
ueventd
源码位于: ./base/startup/init_lite/ueventd
,主要作用是接收uevent
来创建或删除/dev/xxx
(设备节点) 我们来看下它的源码 ueventd.c
:
- 在
/etc/ueventd.config
定义了一些设备节点,ueventd
主要是监控这些节点的事件, 如:/dev/binder, /dev/input/event0, /dev/tty, /dev/graphics/fb0, /dev/i2c-0
等等 - 对
/etc/ueventd.config
进行解析,解析到为[device]
,刚配置回调为callback = funcMapper["device"].func
,也就是ParseDeviceConfig
,回调定义如下:
static FUNCTIONMAPPER funcMapper[3] = {
{
"device", ParseDeviceConfig}, // 在该回调中,将所有需要监控的设备添加在 g_devices链表中
{
"sysfs", ParseSysfsConfig},
{
"firmware", ParseFirmwareConfig}
};
- 创建
uevent socket
,大小为 256k - 将
"/sys/block","/sys/class","/sys/devices"
这些节点与socket
绑定在一起。 - 不停的监控
uevent
是否有poll
事件 - 从处理事件看,
uevent->action
支持ACTION_ADD、ACTION_CHANGE 、ACTION_ONLINE、ACTION_REMOVE
四种事件,根据不同的事件做相应的操作。
# V:\lihaiyan\work\hormony\harmony_3.0\code-v3.0-LTS\OpenHarmony\base\startup\init_lite\ueventd\ueventd.c
int main(int argc, char **argv)
{
// 在/etc/ueventd.config 定义了一些设备节点,ueventd主要是监控这些节点的事件
char *ueventdConfigs[] = {
"/etc/ueventd.config", NULL};
while (ueventdConfigs[i] != NULL) {
ParseUeventdConfigFile(ueventdConfigs[i++]);
------------>
// 省略打开 /etc/ueventd.config 的代码,打开读取内容后,调用DoUeventConfigParse()对每个设备节点进行解析
DoUeventConfigParse(buffer, size);
================>
// 对/etc/ueventd.config 中的[device]进行解析,解析到为[device],刚配置回调为callback = funcMapper["device"].func;
for (int i = 0; i < count; i++) {
ParseUeventConfig(p);
----> callback = funcMapper[type].func;
}
<================
<------------
}
// 创建 uevent socket,大小为 256k
int ueventSockFd = UeventdSocketInit();
// 将 "/sys/block","/sys/class","/sys/devices" 这些节点与 socket绑定在一起。
RetriggerUevent(ueventSockFd);
struct pollfd pfd = {
};
pfd.events = POLLIN;
pfd.fd = ueventSockFd;
// 不停的监控uevent 是否有poll 事件
while (1) {
pfd.revents = 0;
int ret = poll(&pfd, 1, -1);
if (ret <= 0) {
continue;
}
if (pfd.revents & POLLIN) {
ProcessUevent(ueventSockFd);
------>
const char *devName = GetDeviceName(sysPath, uevent->deviceName);
HandleDeviceNode(uevent, deviceNode, isBlock);
// 处理事件看,uevent->action支持ACTION_ADD、ACTION_CHANGE 、ACTION_ONLINE、ACTION_REMOVE 四种事件
=======>
if (uevent->action == ACTION_ADD || uevent->action == ACTION_CHANGE || uevent->action == ACTION_ONLINE) {
ChangeSysAttributePermissions(uevent->syspath);
}
SUBSYSTEMTYPE type = GetSubsystemType(uevent->subsystem);
switch (type) {
case SUBSYSTEM_BLOCK:
HandleBlockDeviceEvent(uevent);
===========>
if (action == ACTION_ADD) {
if (CreateDeviceNode(uevent, deviceNode, symLinks, isBlock) < 0) {
INIT_LOGE("Create device \" %s \" failed", deviceNode);
}
} else if (action == ACTION_REMOVE) {
if (RemoveDeviceNode(deviceNode, symLinks) < 0) {
INIT_LOGE("Remove device \" %s \" failed", deviceNode);
}
} else if (action == ACTION_CHANGE) {
INIT_LOGI("Device %s changed", uevent->syspath);
}
<===============
break;
case SUBSYSTEM_FIRMWARE:
HandleFimwareDeviceEvent(uevent);
break;
case SUBSYSTEM_OTHERS:
HandleOtherDeviceEvent(uevent);
break;
default:
break;
}
<=======
}
}
return 0;
}
1.2 console 终端处理程序,用于用户登录
1.3 hdcd 命令行处理工具守护进程,等同于android的 adb
二、各模块Services简介
系统中的Services 当然不仅仅就前面的三个,我们来运行OHOS 3.0 进入它的shell 环境, 看下 "/etc/"
和 /system/etc/init
下面有哪些.cfg
文件:
# ls /etc/ -al
drwxr-xr-x 2 root root 4096 2021-12-21 05:45 init
-rw-r--r-- 1 root root 27205 2021-12-21 05:45 init.cfg
-rw-r--r-- 1 root root 1077 2021-12-21 05:45 init.usb.cfg
-rw-r--r-- 1 root root 1667 2021-12-21 05:45 init.usb.configfs.cfg
-rw-r--r-- 1 root root 1175 2021-12-21 05:45 ohos.para
-rw-r--r-- 1 root root 2181 2021-12-21 05:45 ueventd.config
# ls /system/etc/init
accountmgr.cfg huks_service.cfg
appspawn.cfg inputmethodservice.cfg
audio_policy.cfg installs.cfg
bytrace.cfg kernel_wifi.cfg
camera_service.cfg lmks.cfg
deviceauth_service.cfg media_service.cfg
distributed_data.cfg medialibrary_service.cfg
distributedpermission_service.cfg pulseaudio.cfg
distributedsched.cfg samgr_L2.cfg
faultloggerd32.cfg softbus_server.cfg
foundation.cfg telephony.cfg
graphic.cfg timeservice.cfg
hdf_devmgr.cfg updater_sa.cfg
hdf_peripheral.cfg weston.cfg
hilogd.cfg wifi_hal_service.cfg
hiview.cfg wifi_standard.cfg
可以看出,各模块的Services
都在/system/etc/init
下。 各模块简单介绍如下:
2.1 accountmgr.cfg 系统帐号组件
在标准系统上,系统帐号组件主要提供分布式帐号登录状态管理能力,支持在端侧对接厂商云帐号应用,提供云帐号登录状态查询和更新的管理能力。
/base/account/os_account
├── common # 公共基础模块
│ ├── account_error # 错误码定义
│ ├── log # 日志打印代码
│ ├── perf_stat # 性能统计
│ └── test # 公共模块测试代码
├── interfaces # 对外接口存放目录
│ └── innerkits # 对内部组件暴露的头文件存放目录
├── kits # 系统帐号组件开发框架
├── sa_profile # 帐号SA配置文件定义目录
├── services # 系统帐号组件服务代码
│ └── accountmgr # 帐号管理服务目录
└── test # 系统帐号组件测试代码
└── resource # 系统帐号组件测试资源
base/account/os_account/services/accountmgr/accountmgr.cfg
{
"jobs" : [{
"name" : "post-fs-data",
"cmds" : [
"start accountmgr"
]
}
],
"services" : [{
"name" : "accountmgr",
"path" : ["/system/bin/sa_main", "/system/profile/accountmgr.xml"],
"uid" : "system",
"gid" : ["system", "shell"],
"writepid" : [
"/dev/cpuset/foreground/tasks",
"/dev/stune/foreground/tasks",
"/dev/blkio/foreground/tasks"
]
}
]
}
2.2 appspawn.cfg 应用孵化器组件
应用孵化器,负责接受应用程序框架的命令孵化应用进程,设置其对应权限,并调用应用程序框架的入口。
base/startup/appspawn_standard
├── include # 应用孵化器组件头文件
├── parameter # 应用孵化器组件系统参数
├── src # 应用孵化器组件源文件
└── test # 应用孵化器组件测试代码
# base/startup/appspawn_standard/appspawn.cfg
{
"jobs" : [{
"name" : "late-fs",
"cmds" : [
"start appspawn"
]
}
],
"services" : [{
"name" : "appspawn",
"path" : ["/system/bin/appspawn"],
"importance" : -20,
"uid" : "root",
"gid" : ["root"]
}
]
}
2.3 audio_policy.cfg 音频组件
audio_policy
主要是用处理音频策略相关事宜,其代码位于:
# foundation/multimedia/audio_standard/services/etc/audio_policy.cfg
{
"jobs" : [{
"name" : "audio_policy_start",
"cmds" : [
"start audio_policy"
]
}
],
"services" : [{
"name" : "audio_policy",
"path" : ["/system/bin/sa_main", "/system/profile/audio_policy.xml"],
"uid" : "system",
"gid" : ["system", "shell"],
"disabled" : 1
}
]
}
2.4 camera_service.cfg 相机组件
相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。 其代码位于: foundation/multimedia/camera_standard/services
/foundation/multimedia/camera_standard # 相机组件业务代码
├── frameworks # 框架代码
│ ├── innerkitsimpl # 内部接口实现
│ │ ├── camera # 相机框架实现
│ │ └── metadata # 元数据实现
│ └── kitsimpl # 外部接口实现
│ └── camera_napi # 相机NAPI实现
├── interfaces # 接口代码
│ ├── innerkits # 内部接口
│ └── kits # 外部接口
├── LICENSE # 许可证文件
├── ohos.build # 构建文件
├── sa_profile # 服务配置文件
└── services # 服务代码
├── camera_service # 相机服务实现
└── etc # 相机服务配置
# foundation/multimedia/camera_standard/services/etc/camera_service.cfg
{
"jobs" : [{
"name" : "boot",
"cmds" : [
"start camera_service"
]
}
],
"services" : [{
"name" : "camera_service",
"path" : ["/system/bin/sa_main", "/system/profile/camera_service.xml"],
"uid" : "cameraserver",
"gid" : ["system", "shell"]
}
]
}
《聊一聊鸿蒙系统中的Camera组件》
2.5 deviceauth_service.cfg 设备认证模块
在OpenHarmony中,设备认证模块作为安全子系统的子模块,负责设备间可信关系的建立、维护、使用、撤销等全生命周期的管理,实现可信设备间的互信认证和安全会话密钥协商,是搭载OpenHarmony的设备进行可信互联的基础平台能力。
设备认证模块当前提供如下功能:
- 设备互信关系管理功能:统一管理设备互信关系的建立、维护、撤销过程;支持各个业务创建的设备互信关系的隔离和可控共享。
- 设备互信关系认证功能:提供认证设备间互信关系、进行安全会话密钥协商的能力,支持分布式软总线实现互信设备间的组网。
为实现上述功能,设备认证模块当前包含设备群组管理、设备群组认证和帐号无关点对点认证三个子模块
其中,
- 设备群组管理服务:统一管理不同业务建立的本设备与其他设备间的互信关系,并对外提供设备互信关系的创建入口 ,完成信任建立后创建帐号无关设备群组,并将信任对象设备添>加进群组;OpenHarmony上各业务可独立创建相互隔离的设备间可信关系。
- 设备群组认证服务:支持已建立可信关系的设备间完成互信关系的认证及会话密钥的协商。
- 帐号无关点对点设备认证:提供设备间基于共享秘密建立一对一互信关系的功能,并支持基于这种互信关系的认证密钥协商。
/base/security/deviceauth
├── frameworks # 设备认证框架层代码
├── hals # 平台相关工具库抽象层
│ ├── inc # 工具库头文件
│ └── src # 工具库源文件
├── interfaces # 对外接口目录
└── services # 设备认证服务层代码
├── common # 公共代码库
├── group_auth # 设备群组认证模块
├── group_manager # 设备群组管理模块
├── module # 认证器模块(包括帐号无关点对点设备认证器)
└── session # 调度及会话管理模块
网上有篇文章介绍了设备认证模块,可以参考下:《详谈鸿蒙系统中的设备认证模块》
# base/security/deviceauth/frameworks/src/standard/deviceauth_service.cfg
"jobs" : [{
"name" :