文章

鸿蒙进程模型深度解析

鸿蒙进程与线程:AppSpawn 孵化、IPC 通信与线程模型。 讲清应用进程启动与跨进程调用,掌握后能答出「鸿蒙 App 进程怎么创建、怎么通信」。

鸿蒙进程模型深度解析

一句话概括

鸿蒙进程模型 = AppSpawn 按需 fork 进程 + AMS 调度 Ability 分配 + 多线程池复用 + IPC 多通道,设计目标是”轻量启动、严格隔离、高效通信”,适配从 128MB IoT 到旗舰手机的设备跨度。

核心知识点

1. AppSpawn——进程创建的”预制件工厂”

1
2
3
4
5
6
7
8
9
10
11
// 传统 Linux fork:每次新进程从 init 开始 → 慢
// Android Zygote:预加载 Framework → fork 时已载入基础类 → 较快
// 鸿蒙 AppSpawn:预加载运行时的最小内核 → fork 时继承 → 最快 + 最省内存

// 流程:
// ① 系统启动时创建 AppSpawn 进程(预加载 ArkCompiler 运行时)
// ② 点击应用 → AMS 通知 AppSpawn → fork 出应用进程
// ③ 应用进程继承 ArkCompiler → 加载用户代码 → 执行
// ④ 退出应用 → 进程回收

// 关键:不需要每个新进程都初始化运行时,fork 开销极低

2. 应用进程内的线程模型

1
2
3
4
5
6
7
8
9
10
11
应用进程
├── 主线程(UI 线程)
│   ├── 处理事件分发
│   ├── 执行 ArkTS 代码(build 等)
│   └── ⚠️ 不能跑耗时操作 → 会卡 UI
├── ArkCompiler 线程
│   └── 执行 JS 字节码、GC
├── Worker 线程池(通过 worker.ThreadWorker 使用)
│   └── 耗时计算(图片处理、数据解析)
└── IO 线程池
    └── 网络请求、文件读写(框架层自动管理)

3. Worker——鸿蒙的并发方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 主线程
const worker = new worker.ThreadWorker('entry/ets/workers/compute.ets');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => {
  this.result = e.data;  // Worker 算完的结果
};

// workers/compute.ets(Worker 线程)
const parentPort = worker.workerPort;
parentPort.onmessage = (e) => {
  const result = heavyComputation(e.data.data);  // 耗时计算在这里
  parentPort.postMessage(result);
};
// ⚠️ Worker 和主线程不共享内存,通过序列化传递数据
// 大数据建议用 SharedArrayBuffer(受限场景)

4. 进程间通信(IPC)三大通道

通道用途性能
Binder(内核级)系统服务调用(AMS、WMS)最快(微内核原生支持)
RPC(Ability 间)应用间 Ability 调用中(序列化开销)
Want 参数传递轻量数据随跳转携带轻(< 200KB)

5. 进程回收策略

1
2
3
4
5
6
7
8
9
// AMS 的进程优先级(从高到低):
// 前台进程(正在交互)            → 打死不杀
// 可见进程(被半透明覆盖)         → 几乎不杀
// 服务进程(Service Extension)   → 低内存才杀
// 缓存进程(在后台但不活动)       → 优先杀
// 空进程(无组件运行)             → 随时杀

// 开发者策略:在 onBackground() 保存关键状态
// 因为切到后台后随时可能被系统回收

其实你每天都在用

  • 应用秒开:AppSpawn fork 继承预热的运行时 → 应用冷启动比传统 fork 方案快 30%+
  • 多任务切换:回到桌面 → 应用进程降为缓存进程 → AMS 内存不足时回收 → 下次打开重新创建
  • 后台下载:切到后台后 ServiceExtension 继续下载 → 下载完通知栏提醒
  • 跨应用分享:图库分享图片到微信 → Binder IPC 传递 Want(uri) → 微信读取图片
  • Worker 处理图片:拍照后用 Worker 做压缩/滤镜 → 不卡主线程 → 处理完 postMessage 回来

常见误解(FAQ)

  • ❌ 误区:「鸿蒙进程模型和 Android 一样用 Zygote」 鸿蒙用的是自研的 AppSpawn,预加载的是 ArkCompiler 运行时而非 Java Framework。场景更广:同一套机制在 128MB IoT 设备和 12GB 手机上都能跑。

  • ❌ 误区:「Worker 和主线程共享内存,跟 Web Worker 一样」 ArkTS 的 Worker 是中线程模型,不共享堆内存,消息传递是序列化拷贝。只有 SharedArrayBuffer 场景下才共享内存(需要 Atomics 同步),且有严格限制。

  • ❌ 误区:「应用退出后进程立刻被销毁」 系统会保留缓存进程一段时间(LRU 策略),以便下次快速启动。只有当内存不足时 AMS 才会按优先级回收。

  • ❌ 误区:「主线程只是跑 UI 的,跟 JS 引擎无关」 ArkTS 的主线程同时运行 UI 事件循环和 ArkCompiler 执行环境。build() 方法、状态更新回调都在主线程执行——这就是为什么同步耗时计算会直接冻住界面。

一句话总结

鸿蒙进程模型的设计哲学是”按需创建、分级存活、轻量通信”——从 AppSpawn 预热 fork 到 AMS 的分级回收,每一步都围绕着”让用户感知不到进程的存在”。

本文由作者按照 CC BY 4.0 进行授权