PostgreSQL 鸿蒙 PC 适配全记录:从原生交叉编译到 HNP 数据库服务闭环

目录

欢迎加入开源鸿蒙PC社区

欢迎在PC社区平台申请新建项目

适配开源地址


一、为什么要适配 PostgreSQL

PostgreSQL 不只是一套关系型数据库,也是许多开发工具、业务系统和数据平台的基础设施。它对标准 SQL、事务、复杂类型、索引和扩展机制的支持较为完整,在本地开发、数据验证、教学实验以及离线应用中都有稳定需求。将 PostgreSQL 带到鸿蒙 PC,意义并不局限于增加一个可以启动的应用:平台上的原生项目可以获得本地数据库服务,开发者也能直接使用熟悉的 psqlinitdbpg_ctl 等工具完成调试和数据处理。

选择 PostgreSQL 还有一层工程价值。它是典型的多进程 C 工程,启动后由 postmaster 创建共享内存并派生后端进程,同时依赖用户身份、信号、动态库、可写数据目录和服务生命周期。这样的项目能够比较全面地检验鸿蒙 PC 原生软件适配链路是否真正打通:不仅要让源码通过 OHOS musl 工具链编译,还要解决进程间共享状态、应用沙箱、系统服务集成、HNP 命令注册和 HAP 签名交付。

本次适配基于 PostgreSQL 20devel 源码,目标设备为 HarmonyOS PC 2in1,目标架构为 arm64-v8a,应用 BundleName 为 com.opensource.postgresql。最终提供两种交付形态:面向产品镜像的原生系统服务,以及面向普通开发和零售设备的"轻量 HAP + 公共 HNP"。本文的真机验证采用第二种形态,数据库内核仍是 aarch64 原生 ELF,并未在 ArkTS 中重写。


二、先确定适配路线:数据库本体不能放进页面生命周期

PostgreSQL 上游默认运行在传统 Unix/Linux 用户空间。鸿蒙 PC 虽然提供 POSIX 能力和 Native SDK,但应用安装、可写目录、公共命令和系统服务都有自己的边界。如果只把 postgres 复制到设备,动态库、数据目录和客户端入口仍然无法形成可用闭环。

适配时将问题拆成四层:

层次 PostgreSQL 的运行要求 鸿蒙侧处理方式
编译层 识别目标平台并生成原生可执行文件、客户端和动态库 新增 OHOS 平台模板,使用 aarch64-unknown-linux-ohos 工具链交叉编译
内核层 postmaster 与后端进程共享主内存区 使用 `MAP_SHARED
运行层 需要稳定的动态库路径、用户身份和可写数据目录 HNP 启动器解析自身安装位置,设置库路径并使用 HiShell 私有目录
交付层 服务端、客户端、共享数据文件必须整体安装 系统镜像提供 init/SELinux 集成;普通设备使用公共 HNP 随 HAP 安装

其中最关键的边界是:HAP 页面不是 PostgreSQL 服务的宿主。页面只承担安装说明和命令提示;真正运行的是 HNP 中的 postgrespsqlinitdbpg_ctl 等程序。用户关闭说明页后,数据库仍按命令行服务的方式工作,不受 ArkUI 页面前后台切换影响。


三、鸿蒙版本的工程结构

仓库保留 PostgreSQL 上游源码树,在平台层和 ohos/ 目录中集中放置适配内容:

text 复制代码
ohos_postgres/
├── configure.ac / configure             # 识别 linux-ohos 目标并选择 OHOS 共享内存实现
├── src/
│   ├── template/ohos                    # OHOS 平台能力与编译开关
│   ├── makefiles/Makefile.ohos          # 动态库链接规则
│   ├── include/port/ohos.h              # 平台头文件隔离层
│   ├── backend/port/ohos_shmem.c        # 匿名共享内存实现
│   ├── common/username.c                # 当前用户名兜底
│   └── interfaces/libpq/fe-auth.c       # libpq 用户名兜底
└── ohos/
    ├── build-ohos.sh                    # 交叉编译并生成系统 rootfs
    ├── build-hnp.sh                     # 打包 PostgreSQL 公共 HNP
    ├── build-hap.sh                     # 构建携带 HNP 的轻量 HAP
    ├── postgresql_ohos_service.c        # 产品镜像服务启动器
    ├── postgresql_hnp_launcher.c        # HNP 命令分发与运行环境设置
    ├── system/etc/init/postgresql.cfg   # OpenHarmony init 服务配置
    ├── sepolicy/                        # 服务域与文件标签模板
    └── app/                             # 2in1 ArkUI 说明页和 HNP 载体

完整的数据流如下:

text 复制代码
PostgreSQL C 源码
    └── OHOS Native SDK 交叉编译
          ├── postgres / initdb / pg_ctl / psql / pg_isready
          ├── libpq 与服务端动态库
          └── share 运行时数据
                 ├── 产品镜像 rootfs + init + SELinux
                 └── postgresql.hnp
                        └── 注入、签名为 HarmonyOS PC HAP

系统镜像形态适合有产品源码和平台签名权限的集成场景;HNP/HAP 形态适合普通设备安装。两者复用同一份 PostgreSQL 原生产物,区别只在服务托管方式和安装边界。


四、从安装说明到事务与持久化的真机验证

以下五张截图均来自已连接的 HarmonyOS PC 2in1 真机,设备截图分辨率为 3120×2080。测试 HAP 已实际安装到设备,终端操作在系统 HiShell 中执行,SQL 结果由 HNP 内的 PostgreSQL 服务实时返回。


1.HAP 负责安装入口和命令说明

应用页展示当前 PostgreSQL 版本和四个最常用的服务入口:postgresql-startpostgresql-clipostgresql-statuspostgresql-stop。首次运行无需手工查找 HNP 解包路径,也不需要把二进制复制到应用目录。

页面中明确说明数据保存在 HiShell 私有目录,服务默认只监听本机 127.0.0.1。这既符合开发者在本机使用数据库的习惯,也避免为了演示而默认开放网络访问。


2.验证原生服务版本和连接就绪状态

启动数据库后,在真机 HiShell 中直接执行 postgres --version,返回 PostgreSQL 20devel;紧接着使用 pg_isready 检查 127.0.0.1:5432,服务返回 accepting connections

这一步验证的是 HNP 公共命令、私有动态库路径、postmaster 进程和 loopback TCP 连接的连续链路。与页面上的静态版本文字相比,终端输出来自真正在设备上执行的原生程序。


3.建表、写入和查询形成最小数据闭环

测试创建 harmony_demo 表,字段包含整数主键、文本和 NUMERIC(8,2) 定点数;随后插入 HarmonyOS PCPostgreSQL 20 两条记录,并按主键查询。

截图中的 DROP TABLECREATE TABLEINSERT 0 2 和最终两行结果均由同一次真机数据库实例产生。它同时覆盖了 DDL、DML、文本编码、定点数存储和客户端表格化输出,不是预先写入页面的演示数据。


4.用 ROLLBACK 验证事务语义

在事务中将第一条记录的价格从 6999.00 临时更新为 1.00,事务内查询能够看到新值;执行 ROLLBACK 后再次查询,价格恢复为 6999.00。

这一结果说明服务端不仅能够解析 SQL,事务状态、行版本和撤销路径也在目标设备上正常工作。对数据库移植而言,事务回滚比单独展示一次查询更能反映内核主链路的完整性。


5.干净重启后数据仍然存在

最后通过 postgresql-stop 正常关闭服务,再执行 postgresql-start 重新拉起实例。重启后的查询仍返回此前写入的两条数据,数值也保持不变。

这张截图把服务生命周期和磁盘持久化放在同一个验证过程中:pg_ctl 完成干净关闭,WAL 与数据文件落盘,重新启动后数据库目录被识别为已有实例,没有重复初始化,客户端随后成功读回原数据。


五、适配过程中最棘手的几个问题

难点一:让 PostgreSQL 正确认出 OHOS,而不是落入未知平台

PostgreSQL 的构建系统会根据 host triplet 选择平台模板、共享库规则和系统能力。如果 aarch64-unknown-linux-ohos 没有独立映射,即使部分源文件能够编译,后续也会在共享内存、动态库和接口探测阶段出现互相矛盾的配置。

适配在 configure.ac 和生成的 configure 中增加 linux-ohos*ohos 模板的映射,并提供 src/template/ohossrc/makefiles/Makefile.ohos。构建脚本统一使用 OHOS SDK 的 clang、llvm-arllvm-ranlibllvm-strip,使编译器、sysroot、musl ABI 与链接器保持同一目标契约。当前 aarch64 产物的 ELF 解释器为 /lib/ld-musl-aarch64.so.1,与设备运行环境一致。


难点二:应用沙箱不能沿用 System V 共享内存

PostgreSQL 主共享内存区保存缓冲区、锁和进程间状态,上游常见路径依赖 System V IPC。HarmonyOS 应用沙箱下直接使用这套机制会受限,数据库即使编译成功,也会在 postmaster 初始化阶段失败。

OHOS 专用实现改用 MAP_SHARED | MAP_ANONYMOUS。postmaster 先创建映射,再由 fork() 生成的后端进程继承同一片共享内存;数据目录中的 postmaster.pid 继续承担单实例互斥。该实现同时明确关闭 huge pages,并保持 PostgreSQL 的动态共享内存使用 POSIX 路径。这样改动集中在平台端口层,不需要侵入缓冲区管理和 SQL 执行逻辑。


难点三:传统 Unix 用户名在应用环境中并不总是存在

PostgreSQL 工具和 libpq 会从当前 UID 查询用户名,但 HarmonyOS 应用 UID 不一定在传统 /etc/passwd 中存在。未处理时,initdb 或客户端默认参数可能在真正连接数据库之前就退出。

适配在服务端公共代码与 libpq 两侧增加 __OHOS__ 条件分支:常规用户查询成功时保持上游行为;查询不到时生成 ohos_<uid> 形式的稳定名称。服务端工具和客户端使用同一兜底规则,避免一侧可初始化、另一侧却无法连接的割裂状态。


难点四:HNP 安装路径动态变化,数据目录又必须可写

公共 HNP 安装后,系统命令入口是软链,真实包目录由安装服务管理,不能在脚本里写死。与此同时,签名包内容只读,数据库目录、日志和 PID 文件必须放到 HiShell 可写范围。

postgresql_hnp_launcher.c 通过 /proc/self/exe 定位当前 HNP,向下找到真正的 bin/lib/,补充 LD_LIBRARY_PATH 后再分发到对应 PostgreSQL 程序。服务别名默认使用 /data/storage/el2/base/files/postgresql-datapostgresql-start 在缺少 PG_VERSION 时才执行初始化。命令因此可以从任意工作目录运行,同时不会把数据写进只读安装包。


难点五:声明了 HNP,不代表它已经进入最终签名包

module.json5 中的 hnpPackages 负责声明公共 Native Package,但普通 Hvigor HAP 任务不会自动把现有 HNP 载荷放进最终产物。只构建页面会得到很小的 HAP,设备安装时也不会出现 PostgreSQL 公共命令。

项目在 HAP 构建后调用 SDK 的 app_packing_tool.jar,通过 --hnp-path 重打未签名 HAP,再使用项目签名链生成最终安装包。打包顺序必须是"编译 ArkTS 页面---注入 HNP---整体签名",否则修改签名后的 HAP 会破坏完整性校验。本次真机安装的 HNP 约 8.6 MB,携带 HNP 的签名 HAP 约 8.8 MB。


六、构建、安装与运行

PostgreSQL 是原生 C 工程,不属于 Electron 或 Qt 项目,因此环境主要由 DevEco Studio/OpenHarmony Native SDK、GNU Make、Java 和 Hvigor 组成。交叉编译 PostgreSQL runtime:

bash 复制代码
OHOS_SDK_NATIVE=/path/to/openharmony/native \
JOBS=8 \
./ohos/build-ohos.sh

默认目标为 aarch64-unknown-linux-ohos,安装前缀为 /system/postgresql。脚本完成 configure、编译、安装、strip 和 rootfs 打包,系统镜像产物位于:

text 复制代码
dist-ohos/aarch64/rootfs/
dist-ohos/aarch64/postgresql-ohos-aarch64-rootfs.tar.gz

面向普通 HarmonyOS PC 设备时,继续生成公共 HNP:

bash 复制代码
./ohos/build-hnp.sh

产物位于:

text 复制代码
ohos/app/hnp/arm64-v8a/postgresql.hnp

随后构建携带 HNP 的 HAP:

bash 复制代码
export DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk
./ohos/build-hap.sh

项目签名配置需与目标设备和 BundleName 匹配。连接设备后安装并启动说明页:

bash 复制代码
hdc list targets
hdc install -r ohos/app/entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.opensource.postgresql -m entry

在系统 HiShell 中启动、检查、连接和停止服务:

bash 复制代码
postgresql-start
pg_isready -h 127.0.0.1 -p 5432
postgresql-cli
postgresql-stop

如果集成到产品镜像,则还需要将 rootfs、postgresql.cfg、用户组片段、SELinux 服务域和 file contexts 一并合入镜像。只复制 /system/postgresql/bin/postgres 不足以构成受 init 正确托管的系统服务。


七、当前功能边界

当前版本已在 HarmonyOS PC 真机上验证以下核心能力:

  • HAP 签名安装、公共 HNP 解包和全局 PostgreSQL 命令注册;
  • postgres --version 原生命令执行;
  • 首次数据目录初始化与重复初始化保护;
  • postmaster 启动、状态检查和干净停止;
  • 127.0.0.1:5432 loopback TCP 连接;
  • psql 客户端执行 DDL、插入和查询;
  • 文本、整数和 NUMERIC 数据读写;
  • BEGINUPDATE、事务内查询与 ROLLBACK
  • 服务正常停止、重新启动后的数据持久化;
  • 产品镜像所需的 init、服务启动器和 SELinux 集成模板。

适配范围同样保持明确。当前构建使用 --without-icu--without-readline--without-zlib--disable-nls,TLS 也未作为本轮默认能力开启;HNP 服务默认只监听 127.0.0.1,没有把远程访问、外部认证和公网暴露描述为已完成。完整上游回归测试、强杀恢复、磁盘满、低内存和长时间压力运行仍属于后续生产化验证范围。

因此,当前版本更准确的定位是"可在 HarmonyOS PC 真机本地运行的 PostgreSQL 20devel 原生开发与实验版本"。它已经覆盖数据库主流程和两种交付框架,但不等同于经过完整容灾、性能和安全认证的生产发行版。


八、总结

PostgreSQL 的鸿蒙 PC 适配表明,数据库项目的难点从来不只是把源码编译成 aarch64 文件。平台识别、共享内存、用户身份、动态库、数据目录、服务生命周期和签名包必须形成连续约束,其中任意一环脱节,最终都会表现为"有产物但不可用"。

本项目通过 OHOS 平台模板和 musl 工具链完成原生交叉编译,用匿名共享内存保留 postmaster 多进程架构,用统一用户名兜底解决应用 UID 差异,再由 HNP 启动器处理动态安装路径和私有数据目录。系统镜像形态与 HNP/HAP 形态共享同一套数据库内核,分别覆盖产品集成和普通设备使用。

真机上的版本检查、连接就绪、建表写入、事务回滚以及重启后持久化,说明当前适配已经越过"能够生成安装包"的阶段,形成了可以处理真实数据的最小数据库闭环。这套方法也适用于其他依赖多进程、共享内存和系统服务的原生基础软件:先解决平台契约,再解决运行边界,最后用目标设备上的真实业务操作验收。

相关推荐
lqj_本人1 小时前
Tftpd64 鸿蒙 PC 适配全记录:用 Qt 重建一组可运行的 UDP 网络服务
qt·udp·harmonyos
风哥2号1 小时前
数据库教程FGMT26‑2-GoldenGate数据库容灾迁移02(OGG同构异构、数据库迁移、数据同步、容灾复制)
数据库·goldengate
User_芊芊君子1 小时前
RStudio 鸿蒙 PC 适配全记录:以 Qt 原生工作区承载嵌入式 R
qt·r语言·harmonyos
牛油果子哥q1 小时前
向量数据库原理与工程选型:FAISS深度剖析、Milvus基础、检索优化、分片与持久化落地
数据库·milvus·faiss
ai安歌1 小时前
Git Extensions 鸿蒙 PC 适配全记录:从 WinForms 客户端到 ArkUI 原生工作台
git·华为·harmonyos
海浪仙人掌2 小时前
流动比率有哪些分析陷阱?流动比率怎么避开这些陷阱?
大数据·数据库·人工智能
●VON2 小时前
Flutter 鸿蒙插件适配实战:用 accurate_storage_info 0.1.1 查询总量、可用量与已用量
flutter·华为·harmonyos
网络豆2 小时前
Apache Maven 鸿蒙 PC 适配全记录:把 JVM 构建工具交付到 HiShell
maven·apache·harmonyos
鸽芷咕2 小时前
MySQL Server 鸿蒙 PC 适配全记录:以混合工具链完成 C++23 交叉编译与 HNP 交付
adb·harmonyos·c++23