OpenHarmony 技术拆解(一):多内核兼容与硬件能力发布机制
做嵌入式系统移植时,最麻烦的往往不是业务代码,而是底层差异。
同样是创建线程,Linux 用 pthread_create(),LiteOS 用 LOS_TaskCreate();同样是等待信号量,不同内核的 API、超时语义、返回值都不一样。文件系统、内存映射、中断处理、定时器也都有类似问题。
OpenHarmony 面对的问题更复杂。它需要覆盖标准系统、小型系统和轻量系统,对应的底层内核分别可能是 Linux、LiteOS-A 和 LiteOS-M。也就是说,同一套系统框架既要能跑在手机、平板、车机这类资源充足的设备上,也要能跑在 MCU 或轻量 IoT 节点上。
这篇文章围绕一个核心问题展开:OpenHarmony 如何在不同内核之上建立统一的系统服务、驱动框架和硬件能力发布机制。
文章重点讨论四件事:
-
OpenHarmony 为什么需要同时支持 Linux、LiteOS-A、LiteOS-M。
-
OSAL 和 HDF 分别解决什么问题,它们不解决什么问题。
-
Linux 原生设备驱动是否需要迁移到 HDF,以及如何发布成 OpenHarmony 硬件能力。
-
被发布的硬件能力如何被其他节点使用,UART、Timer、IRQ 这类启动关键能力又该如何处理。
1. 多内核兼容的整体分层
OpenHarmony 的多内核兼容不是在一个内核里做很多开关,而是在系统架构上把"内核相关"和"内核无关"的部分隔离开。
从上到下可以分成几层:
-
应用层:ArkTS、JS、C/C++ 应用。
-
框架层:Ability、ArkUI、多媒体、通信、分布式能力等。
-
系统服务层:包管理、窗口、电源、传感器、输入、音频、显示等服务。
-
HDF 驱动框架:统一驱动模型、设备管理、Host、Dispatch。
-
OSAL 操作系统抽象层:线程、锁、信号量、定时器、内存、文件、I/O 等基础 OS 能力封装。
-
内核层:Linux、LiteOS-A、LiteOS-M。
-
硬件层:SoC、MCU、传感器、通信模组、显示屏等。
!外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Finternal-api-drive-
图1展示了这套分层关系。
图1的关键点在于,系统服务及以上不直接感知底层内核。它们通过 HDF/HDI 访问硬件能力,而 HDF 内部需要调用线程、锁、内存、I/O 等基础能力时,再通过 OSAL 适配到底层内核。
因此,OpenHarmony 的多内核兼容并不是靠上层代码到处写 #ifdef Linux、#ifdef LiteOS,而是把差异集中收敛到 HDF 适配层和 OSAL 实现里。
2. 三类内核对应三种系统形态
OpenHarmony 支持三种典型系统形态:标准系统、小型系统和轻量系统。它们面对的硬件规模差异很大。
| 内核 | 系统形态 | 典型设备 | MMU | 内存规模 |
|---|---|---|---|---|
| Linux | 标准系统 | 手机、平板、车机、开发板 | 有 | 通常大于 128 MB |
| LiteOS-A | 小型系统 | 智能屏、摄像头、部分工业设备 | 有 | 通常大于 1 MB |
| LiteOS-M | 轻量系统 | MCU、传感器节点、低功耗 IoT 设备 | 无 | 可低至几十 KB |
Linux 提供完整的进程模型、VFS、网络协议栈、驱动模型和内存管理,适合标准系统。LiteOS-A 更轻量,但仍有 MMU 和类 POSIX 能力,适合小型系统。LiteOS-M 面向 MCU,通常没有 MMU,任务共享地址空间,很多能力直接依赖 BSP/HAL。
硬件规模差异决定了 OpenHarmony 不可能用一个内核覆盖所有场景。它的策略是:
-
上层服务和接口尽量统一。
-
底层内核根据设备形态选择。
-
内核差异通过 OSAL、HDF 适配层和产品配置隔离。
3. OSAL 解决的是基础 OS API 差异
OSAL,全称 Operating System Abstraction Layer,作用是为上层组件提供统一的基础操作系统接口。
这些接口通常包括:
-
线程创建与销毁。
-
互斥锁、信号量、自旋锁。
-
定时器。
-
内存分配和映射。
-
文件操作。
-
I/O 操作。
-
中断注册。
-
时间获取。
上层代码不直接调用 pthread_create()、LOS_TaskCreate() 或 CMSIS RTOS API,而是通过 OsalThreadCreate() 这一类接口间接访问底层能力。

图2展示了 OSAL 的映射方式。
以线程、锁、信号量为例,不同内核的映射大致如下:
C
// Linux
OsalThreadCreate() -> pthread_create() / kthread_run()
OsalMutexLock() -> pthread_mutex_lock() / mutex_lock()
OsalSemWait() -> sem_wait()
C
// LiteOS-A
OsalThreadCreate() -> LOS_TaskCreate()
OsalMutexLock() -> LOS_MuxPend()
OsalSemWait() -> LOS_SemPend()
C
// LiteOS-M
OsalThreadCreate() -> LOS_TaskCreate() / CMSIS osThreadNew()
OsalMutexLock() -> LOS_MuxPend() / CMSIS osMutexAcquire()
OsalSemWait() -> LOS_SemPend() / CMSIS osSemaphoreAcquire()
OSAL 的价值不在于把 Linux API 再包一层。对于 Linux 来说,OSAL 很多时候只是薄封装。它真正的价值在于:同一套 HDF 驱动框架或可移植组件,在切到 LiteOS-A、LiteOS-M 时不需要重写基础 OS 调用。
不过,OSAL 只能统一接口,不能完全消除语义差异。
例如:
-
Linux 和 LiteOS-A 有 MMU,
mmap可以表示虚拟地址映射;LiteOS-M 通常没有 MMU,类似接口可能只是在物理地址或静态内存上做封装。 -
Linux 的中断上下文、进程上下文分得很清楚;LiteOS-M 的模型更接近传统 MCU RTOS,任务和中断的边界不同。
-
Linux 的线程调度、优先级、阻塞语义与 LiteOS 并不完全一致。
因此,使用 OSAL 并不意味着不用理解底层内核。它解决的是工程上的接口收敛,不是把所有内核语义变成同一种东西。
4. OSAL 不参与 Linux 启动
讨论 OpenHarmony 标准系统时,一个常见误区是把 OSAL 理解成 Linux 启动的一部分。
实际上,Linux 的启动链路完全由 BootROM、Bootloader 和 Linux Kernel 自己完成。OSAL 在这个阶段并不存在。
标准系统的启动过程可以简化为:
Plain
BootROM -> SPL -> U-Boot -> Linux start_kernel() -> rootfs -> OpenHarmony init
在 Linux start_kernel() 阶段,内核会完成 MMU、调度器、中断控制器、时钟、驱动核心、VFS、根文件系统等初始化工作。这些都属于 Linux 内核职责,不依赖 OpenHarmony OSAL。
OpenHarmony 真正接管系统,是在 Linux 内核拉起第一个用户态进程之后。标准系统中,这个进程是 OpenHarmony 的 init。
OH init 读取启动配置,按阶段拉起系统服务,例如:
-
samgr -
foundation -
hdf_devmgr -
hdf_host -
各类 native service
OSAL 从这些系统服务和 HDF 组件运行后才开始发挥作用。图3展示了 Linux 启动链路中 OSAL 的位置。
所以,更准确的说法是:OSAL 不支持 Linux 启动,它支持 OpenHarmony 在 Linux 启动完成之后继续以跨内核方式运行系统服务和驱动框架。
5. HDF 统一的是驱动模型和硬件服务接口
OSAL 解决基础 OS API 差异,HDF 解决驱动模型和硬件服务接口的统一。
HDF 大致可以分为几层:
-
驱动管理层:负责驱动加载、设备管理、Host 管理、Dispatch。
-
驱动模型层:例如 Platform、Sensor、Display、Input、Audio、WLAN、USB 等模型。
-
适配层:在需要调用底层 OS 或 Linux 原生接口时进行适配。

图3展示了 HDF 与不同内核之间的关系。
在标准系统上,HDF 并不是用来替代 Linux Driver Model 的。Linux 原生驱动体系仍然存在,HDF 更像是 OpenHarmony 的硬件服务治理层。
两条访问路径可以并行存在:
Plain
OpenHarmony 应用 / 系统服务
|
|-- HDI / HDF -> HDF Service / HDF Host -> Linux 原生接口或 HDF 驱动
|
|-- syscall / ioctl / read / write -> Linux 原生驱动
这意味着,Linux 标准系统上的设备驱动不需要全部迁移到 HDF。是否迁移取决于这个硬件能力是否需要被 OpenHarmony 统一管理,是否需要通过 HDI 暴露给上层,是否需要进一步通过 DSoftBus 发布给其他节点。
6. Linux 原生驱动是否需要迁移到 HDF
标准系统中,Linux 内核已经提供了完整驱动体系。例如:
-
块设备驱动。
-
网络驱动。
-
V4L2 Camera 驱动。
-
ALSA Audio 驱动。
-
IIO 传感器驱动。
-
GPIO、PWM、I2C、SPI 等基础总线和控制器驱动。
这些驱动没有必要全部重写成 HDF。更合理的做法是分类处理。
6.1 必须纳入 HDF/HDI 的能力
如果硬件能力需要被 OpenHarmony 系统服务统一管理,或者需要通过分布式能力暴露给其他设备,一般需要纳入 HDF/HDI。
典型场景包括:
-
分布式传感器。
-
分布式显示。
-
输入设备统一管理。
-
USB 设备管理。
-
需要被上层框架标准化调用的音频、显示、相机、传感器等模块。
这类能力的重点不是"驱动必须重写",而是必须提供标准 HDI 接口。
6.2 封装适配即可的能力
很多外设底层仍然使用 Linux 原生驱动,上层通过 HDF/HDI 或 HAL 做一层封装。
例如:
-
Camera 底层仍可能走 V4L2 / Media Controller。
-
Audio 底层仍可能走 ALSA / tinyalsa。
-
WLAN 底层仍可能走 cfg80211 / nl80211。
-
Sensor 底层可能走 IIO、input 子系统或厂商私有节点。
这种方式更接近 Adapter 模式:底层驱动不动,上层提供 OpenHarmony 统一接口。
6.3 可以保留 Linux 原生访问的能力
如果某个硬件只在本机使用,不需要通过 OpenHarmony 系统服务治理,也不需要分布式发布,可以继续使用 Linux 原生接口。
例如:
-
eMMC、SD、NAND 等块设备。
-
内部 I2C/SPI 总线上的 PMIC 或板级控制器。
-
只通过 sysfs 控制的简单 GPIO/PWM。
-
看门狗、部分电源管理、内部调试设备。

图4给出了一个判断流程。
工程上建议先保留 Linux 原生驱动,把内核、rootfs、OH init 和基础服务跑通。只有当上层服务需要 HDI 接口,或者硬件能力需要分布式发布时,再做 HDF/HDI 适配。
7. 如何把 Linux 原生驱动发布成 OpenHarmony 硬件能力
把 Linux 原生驱动接入 OpenHarmony,不等于重写内核驱动。常见做法是在原生驱动之上增加 Adapter 和 HDI Server。
以一个 Linux IIO 传感器为例,底层已经存在这些节点:
Plain
/dev/iio:device0
/sys/bus/iio/devices/iio:device0/in_accel_x_raw
/sys/bus/iio/devices/iio:device0/in_accel_y_raw
/sys/bus/iio/devices/iio:device0/in_accel_z_raw
推荐的发布路径如下:
Plain
Linux 原生驱动
|
|-- /dev / sysfs / ioctl / read / mmap
|
Adapter 适配层
|
|-- 将 Linux 私有接口翻译成模块语义
|
HDI Server
|
|-- 实现 IDL 生成的接口
|
HDF/HCS 注册
|
OpenHarmony 系统服务
|
DSoftBus 远端代理

图5展示了这个路径。
Adapter 层可以直接使用 Linux 原生接口,例如:
C
int32_t LinuxAccelAdapterEnable(int32_t sensorId)
{
int fd = open("/dev/iio:device0", O_RDONLY);
if (fd < 0) {
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t LinuxAccelAdapterRead(struct SensorData *data)
{
/* 从 sysfs、ioctl 或 mmap ring buffer 中读取数据,
再转换成 OpenHarmony SensorData 结构。 */
return HDF_SUCCESS;
}
随后通过 IDL 定义 HDI 接口:
Plain
package ohos.hdi.sensor.v1_0;
interface ISensorInterface {
EnableSensor([in] int sensorId);
DisableSensor([in] int sensorId);
SetBatch([in] int sensorId, [in] long samplingInterval);
GetAllSensorInfo([out] struct SensorInfo[] info);
}
IDL 编译后生成 client/server 相关代码。服务端实现中再调用 Adapter:
C
int32_t EnableSensor(int32_t sensorId)
{
return LinuxAccelAdapterEnable(sensorId);
}
然后通过 HCS/HDF 注册服务:
C
sensor_host :: host {
hostName = "sensor_host";
priority = 100;
sensor_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 100;
moduleName = "sensor_driver";
serviceName = "sensor_service";
match_attr = "linux_accel_sensor";
}
}
}
这样,上层看到的是标准 HDI 能力,底层仍然可以保留成熟的 Linux 驱动。
8. 被发布的硬件能力如何被其他节点使用
OpenHarmony 的分布式能力不是把一个设备的驱动搬到另一个设备上运行。远端节点拿到的是代理对象,真正访问硬件的仍然是硬件所在节点。
假设节点 A 上有一个传感器,已经通过 HDI 发布;节点 B 希望使用这个传感器。调用链路可以简化为:
Plain
节点 B 应用
|
Remote Proxy
|
DSoftBus 会话通道
|
节点 A HDI Service
|
Adapter / HDF Driver
|
Linux 原生驱动或 LiteOS 驱动
|
真实硬件
远端调用过程通常包括:
-
设备发现:DSoftBus 发现附近可信设备。
-
认证组网:完成设备认证、可信关系校验和组网。
-
能力发现:系统服务识别远端节点提供的硬件能力。
-
获取代理:调用方拿到 Remote Proxy。
-
发起调用:Proxy 将请求序列化,经 DSoftBus 发送到硬件所在节点。
-
本地执行:节点 A 的 HDI Service 调用本地 Adapter 或 HDF Driver。
-
数据返回:结果或数据流经 DSoftBus 回传给节点 B。
控制类接口通常走同步调用,例如 Enable、Disable、Config。数据上报更适合异步回调或流式传输,例如传感器连续采样、音视频数据等。
DSoftBus 提供多类传输通道:
| 通道类型 | 适合场景 | 示例 |
|---|---|---|
| message | 控制命令、小数据 | 开关传感器、配置参数 |
| bytes | 中等大小结构化数据 | 传感器批量数据、定位坐标 |
| stream | 连续流数据 | 音频、视频、高频传感器数据 |
| file | 文件传输 | 日志、图片、升级包 |
远端节点不访问 /dev/iio:device0,也不加载节点 A 的 .ko。它调用的是标准化能力代理。
9. 被发布的驱动能力是否必须使用 OSAL 编写
不一定。
OSAL 适用于需要跨内核复用的代码。如果一段 HDF 驱动逻辑需要同时跑在 Linux、LiteOS-A 和 LiteOS-M 上,就应该使用 OSAL 来封装线程、锁、内存、中断、定时器等基础能力。
但如果只是标准系统上的 Linux-only Adapter,直接使用 POSIX、syscall、ioctl()、read()、write() 通常更直接。
可以按下面的原则判断:
| 场景 | 是否建议使用 OSAL |
|---|---|
| 跨 Linux、LiteOS-A、LiteOS-M 的 HDF 通用驱动逻辑 | 建议使用 |
| 只在 Linux 标准系统运行的 HDI Adapter | 不强制,直接使用 Linux 原生接口更清晰 |
用户态服务封装 /dev、sysfs、V4L2、ALSA、cfg80211 |
通常不需要 |
| 启动早期 BSP、Bootloader、内核自举代码 | 不能依赖 OSAL |
OSAL 是跨内核移植工具,不是所有硬件能力发布都必须经过的唯一入口。
10. UART、Timer、IRQ 的处理边界
UART、Timer、IRQ 这类能力比较特殊,因为它们既可能是操作系统启动基础设施,也可能是业务外设能力。
必须先区分两个阶段:
| 阶段 | 使用者 | 目的 | 处理方式 |
|---|---|---|---|
| 启动支撑阶段 | Bootloader、内核、BSP | 让系统先启动起来 | OS/BSP 原生处理 |
| 业务运行阶段 | 应用、系统服务、HDF/HDI | 对外提供外设访问能力 | 可通过 Linux 原生接口、OSAL、HDF/HDI 封装 |
10.1 UART
启动阶段的串口一般用于 early console、Bootloader 日志、内核启动日志。这条链路通常是:
Plain
BootROM -> SPL -> U-Boot -> Linux earlycon / console
这些能力在 HDF 启动之前就必须可用,因此不能依赖 HDF 或 OSAL。
系统运行后,如果某个业务模块需要访问串口,例如 GPS 模块、4G 模块 AT 命令,可以有两种方式:
-
直接操作
/dev/ttySx,使用标准 Linux 用户态接口。 -
通过 HDF UART 模型或 HDI 服务封装成标准能力。
本机使用时,直接访问 Linux 串口节点通常更简单。需要跨内核复用或远端发布时,再考虑 HDF/HDI。
10.2 Timer
系统调度依赖的 timer 属于内核基础设施。例如 Linux 的 clocksource、clockevent、hrtimer,LiteOS 的系统 tick 和软件定时器基础实现。
这些能力位于 OSAL 之下,不能由 OSAL 负责初始化。
OSAL 提供的 timer 更适合业务逻辑,例如:
Plain
Linux : OsalTimerCreate() -> timer_create() / timer_settime()
LiteOS-A : OsalTimerCreate() -> LOS_SwtmrCreate()
LiteOS-M : OsalTimerCreate() -> LOS_SwtmrCreate() / CMSIS osTimerNew()
10.3 IRQ
中断控制器初始化由内核或 BSP 完成。例如 Linux 的 irqchip、GIC、device tree 中断描述,LiteOS-M 的 NVIC 配置。
OSAL 不负责初始化中断控制器。它能做的是在驱动运行阶段注册设备中断处理函数,例如:
Plain
Linux : OsalRequestIrq() -> request_irq()
LiteOS-A : OsalRequestIrq() -> LOS_HwiCreate()
LiteOS-M : OsalRequestIrq() -> HAL/NVIC 相关封装
因此可以这样理解:
-
中断控制器归 OS/BSP。
-
设备中断 handler 归驱动。
-
如果驱动需要跨内核复用,中断注册可以通过 OSAL 封装。
11. 移植时的工程顺序
如果要把一块 Linux 板子适配到 OpenHarmony 标准系统,不建议一开始就重写驱动。更稳妥的顺序是:
-
保留 Linux 原生驱动,先保证内核启动、串口日志、rootfs、基础设备节点正常。
-
拉起 OpenHarmony init,确认系统服务启动顺序和权限配置正确。
-
验证
/dev、/sys、dmesg、hilog,确认底层硬件链路稳定。 -
找出需要接入 OpenHarmony 系统服务的硬件能力。
-
对这些能力编写 Adapter 和 HDI Server。
-
需要分布式发布时,再接入 DSoftBus 能力发现与远端代理调用。
-
只有当代码确实需要跨 Linux、LiteOS-A、LiteOS-M 复用时,再将内部 OS 调用整理为 OSAL。

图6给出了一个简化的移植检查清单。
这个顺序的重点是:先让系统启动,再让硬件可用,最后再做标准化和分布式发布。不要在底层链路还没稳定时急着重构驱动模型。
12. 总结
OpenHarmony 的多内核兼容不是把所有驱动都重写一遍,也不是让所有底层能力都走 OSAL/HDF。
更准确的理解是:
Plain
启动关键路径:
BootROM / SPL / U-Boot / Linux Kernel / LiteOS Kernel
|
OS/BSP 原生能力:UART console / timer tick / irqchip / MMU / scheduler
|
OpenHarmony init:拉起系统服务、HDF Manager、HDI Server
|
HDF/HDI:把需要治理和发布的硬件能力标准化
|
DSoftBus:把标准化后的能力暴露给远端节点
|
远端应用:拿到 Proxy,像调用本地接口一样调用远端硬件能力
可以用几句话收束:
-
OSAL 不参与 Linux 启动,它在系统服务和 HDF 运行后负责抹平跨内核 API 差异。
-
HDF 不替代 Linux Driver Model,它在标准系统上更像硬件服务治理框架。
-
Linux 原生驱动大多数可以保留,需要发布为 OpenHarmony 能力时,优先通过 Adapter + HDI Server 封装。
-
远端节点使用的是能力代理,不是远程加载驱动。
-
UART、Timer、IRQ 等启动关键能力归 OS/BSP,业务阶段才可能通过 OSAL/HDF/HDI 封装。
最终结论是:OpenHarmony 建立的不是一套新的底层驱动体系,而是在已有 OS 和驱动之上,增加了一套可治理、可分布式、可跨内核复用的硬件能力发布机制。