OpenHarmony LiteOS-M 产品参数全为空?一起因初始化顺序引发的调试实录

问题现象

在龙芯 LS2K300 平台(OpenHarmony 6.1,LiteOS-M 内核)上运行 HCTest 测试框架时,系统输出的产品参数信息全部为空值或占位符 "****"

复制代码
******To Obtain Product Params Start******
  Device Type = NULL
  Security Patch = NULL
  OsFullName = 
  DisplayVersion = NULL
  VersionID = 
  DevUdid = NULL
  manuFacture = NULL
  productModel = NULL
  serial = ****
  brand = NULL
  productSeries = NULL
  softwareModel = NULL
  HardwareModel = NULL
  BuildRootHash = NULL
  marketName = NULL
  SdkApiVersion = 0
  firstApiVersion = 0
  bootloaderVersion = NULL
  incrementalVersion = NULL
  buildType = NULL
  buildUser = NULL
  buildHost = NULL
  buildTime = NULL
  AbiList = NULL
******To Obtain Product Params End ******

唯一看起来有值的 serial = **** 其实也是默认占位符,并非真正的设备序列号。这些参数的缺失会导致依赖产品信息的系统服务或应用无法正常运行。

表层原因:缺少平台 HAL 适配

初步排查发现,vendor/loongson/ls2k300_mini_dp 目录下缺少 hals/utils/sys_param/ 平台适配实现。构建系统找不到板级 HAL 库时,会回退到 base/startup/init/interfaces/hals/utils/sys_param/hal_sys_param.c 中的通用默认实现,该实现所有字段均返回 "****"

为此,我们在板级目录下创建了以下三个文件:

复制代码
vendor/loongson/ls2k300_mini_dp/hals/utils/sys_param/
├── hal_sys_param.c   # 实现所有 HalGet*() 函数,填入真实设备信息
├── BUILD.gn          # 声明 hal_sysparam 静态库
└── vendor.para       # 运行时参数服务读取的 key=value 配置文件

hal_sys_param.c 中实现了如下函数(示例):

c 复制代码
const char *HalGetManufacture(void) { return "Loongson"; }
const char *HalGetDeviceType(void) { return "mini"; }
const char *HalGetHardwareModel(void) { return "LS2K300V1.0"; }
// ... 其他字段类似

同时,vendor.para 文件以 key=value 格式提供运行时参数:

复制代码
const.ohos.serial=0123456789abcdef
const.ohos.hardwaremodel=LS2K300V1.0
const.ohos.version.security_patch=2024-01-01
const.ohos.apiversion=12
const.product.manufacturer=Loongson
...

然而,重新编译后,问题依旧存在------HCTest 输出的产品参数仍然全部为空。

深层根因:参数服务初始化顺序竞争

进一步分析 LiteOS-M 内核上产品参数的获取流程:

复制代码
GetDeviceType() / GetManufacture() / ...
    ↓
GetProperty("const.product.*")
    ↓
SystemReadParam()                    // 从参数服务读取

关键发现 :在 LiteOS-M(mini 系统)上,上述接口并不直接调用 HalGetXxx(),而是通过 GetProperty() 从参数服务(LiteParamService)的内存工作区读取值。

参数服务的初始化函数 LiteParamService 和 HCTest 框架的初始化函数 InitTestSuiteMgr 均使用 CORE_INIT() 宏注册 ,该宏默认优先级为 2。同一优先级内的函数执行顺序由链接器决定,不可控

InitTestSuiteMgr 恰好在 LiteParamService 之前执行时,参数服务的工作区尚未初始化,此时任何 GetProperty() 调用都会因工作区为空而返回 NULL。这就是即使 HAL 层已正确实现、配置文件也已提供,产品参数依然全为空的根本原因。

时序示意图

复制代码
系统启动 → CORE_INIT 阶段(优先级 2)
              │
              ├─ InitTestSuiteMgr()  ← 若先执行,参数服务未就绪,读取失败
              │
              └─ LiteParamService()  ← 初始化参数工作区,加载 vendor.para

修复方案:提升参数服务初始化优先级

为解决该竞争问题,我们将 LiteParamService 的初始化优先级从默认的 2 提升至 0,确保它在所有默认优先级的初始化函数之前运行。

文件base/startup/init/services/param/liteos/param_service.c 第 148 行

c 复制代码
// 修改前
CORE_INIT(LiteParamService);

// 修改后
CORE_INIT_PRI(LiteParamService, 0);

CORE_INIT_PRI 宏会将函数指针放入 .zinitcall.core0.init 段,该段中的函数会在系统启动最早阶段执行(优先级 0),远早于默认优先级 2 的其他 CORE_INIT 函数。

安全性说明

  • LiteParamService 函数内部已有 static int init 标志防止重复初始化,即使 system_init.c 中还存在显式调用也不会重复执行。
  • 提升优先级仅影响 LiteOS-M 内核的参数服务,不改变其他模块的初始化顺序。
  • 其他所有依赖参数服务的组件(包括 HCTest)都能在运行时获得已就绪的参数工作区。

验证结果

应用上述两项修改(添加平台 HAL 适配 + 提升参数服务优先级)后,重新构建并烧录镜像,HCTest 框架输出如下:

复制代码
******To Obtain Product Params Start******
Device Type = default
Security Patch = 2026/02/01
OsFullName = OpenHarmony-6.1.0.31
DisplayVersion = OpenHarmony 6.1.0.31
VersionID = default/Loongson/Loongson/LS2K0300/OpenHarmony-6.1.0.31/LS2K0300/LiteOS-M/23/OpenHarmony 6.1 rel/debug
DevUdid = EDD27AEB735CF09FE6AF91F25782BECB1A55DA4CA9A3F9E38DA86DFDDAB45FC0
manuFacture = Loongson
productModel = LS2K0300
serial = 0123456789abcdef
brand = Loongson
productSeries = LS2K0300
softwareModel = LiteOS-M
HardwareModel = LS2K0300V1.0
BuildRootHash = default
marketName = LS2K0300 Mini
SdkApiVersion = 23
firstApiVersion = 1
bootloaderVersion = bootloader
incrementalVersion = OpenHarmony 6.1 rel
buildType = debug
buildUser = jenkins
buildHost = linux
buildTime = 1776392302060
AbiList = loongarch64-liteos
******To Obtain Product Params End  ******

所有产品参数均正常显示,问题彻底解决。

总结与启示

本次调试过程揭示了两层隐蔽的技术陷阱:

  1. 平台 HAL 适配缺失导致回退默认值:构建系统在找不到板级实现时会自动回退到通用实现,该实现往往仅返回占位符,不会产生编译错误,极易被忽略。
  2. 初始化顺序竞争:在 LiteOS-M 这类资源受限、启动流程紧凑的内核上,依赖同一优先级初始化的组件之间存在竞态风险。当某个服务消费者在服务提供者之前初始化时,读取操作会静默失败(返回 NULL),而不会触发明显错误。

通用排查建议

  • 若发现系统参数输出为 "****"NULL,首先检查板级目录下是否提供了 hals/utils/sys_param/ 实现。
  • 若 HAL 已正确实现但运行时仍为空,请检查参数服务初始化是否在所有消费者之前完成。
  • 对于 LiteOS-M 平台,可借助链接 Map 文件查看 .zinitcall.coreX.init 段中函数的实际排布顺序,以诊断初始化顺序问题。
相关推荐
九流下半3 天前
OpenHarmony签名指南:自动与手动详解
签名·openharmony·系统信息·系统应用签名
特立独行的猫a8 天前
使用 vcpkg 为OpenHarmony(鸿蒙PC)构建 OpenSSH 命令行工具
harmonyos·openharmony·命令行·openssh·vcpkg·鸿蒙pc
特立独行的猫a9 天前
HarmonyOS 鸿蒙PC三方库移植:vcpkg方式的 Port 脚本编写简明教程
华为·harmonyos·openharmony·vcpkg·三方库移植
特立独行的猫a10 天前
HarmonyOS / OpenHarmony 平台三方库移植:使用vcpkg 移植 Crashpad 过程实战总结
harmonyos·移植·openharmony·vcpkg·crshpad
特立独行的猫a11 天前
HarmonyOS鸿蒙三方库移植:选 vcpkg 还是 lycium_plusplus?两种“框架化”方案对比
harmonyos·openharmony·vcpkg·三方库移植·鸿蒙pc·lycium_plusplus
左手厨刀右手茼蒿12 天前
Flutter 组件 sheety_localization 的适配 鸿蒙Harmony 实战 - 驾驭在线协作式多语言管理、实现鸿蒙端动态词条下发与全球化敏捷发布方案
flutter·harmonyos·鸿蒙·openharmony·sheety_localization
特立独行的猫a12 天前
使用 vcpkg 为鸿蒙(HarmonyOS / OHOS)下载与安装三方库实践指南
华为·harmonyos·openharmony·vcpkg·三方库·鸿蒙pc
特立独行的猫a14 天前
OpenHarmony平台移植 gifsicle:C/C++ 三方库适配实践(Lycium / tpc_c_cplusplus)
c语言·c++·harmonyos·openharmony·三方库适配·lycium
小菜刀_14 天前
OpenHarmony LiteOS-M LittleFS 文件系统调试与修复实战
openharmony·loongarch·liteos-m