鸿蒙的服务不靠吆喝,全靠 SAMgr 在背后调度?”——系统服务框架全解析!

举报
bug菌 发表于 2025/11/01 22:03:59 2025/11/01
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8 前言很多同学第一次接触鸿蒙底层时都会迷惑:“系统服务到底是谁管的?谁来...

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

很多同学第一次接触鸿蒙底层时都会迷惑:“系统服务到底是谁管的?谁来拉起?我能不能自己加一个?”
答案是——HarmonyOS 的 系统服务管理框架(System Ability Manager, 简称 SAMgr) 就是幕后导演,它掌控着整个系统服务的注册、发现、启动、生命周期和通信
今天我们把这个“隐形总导演”掀开看看,从理念到代码,一次讲透:

一、SAMgr 设计理念:一切服务皆 SystemAbility

1.1 为什么要 SAMgr?

在传统 OS(如 Android、Linux)中,系统服务往往是:

  • 各自独立的进程或守护;
  • 用 binder 或 socket 自行通信;
  • 依赖 init 脚本手动拉起。

鸿蒙希望所有系统能力都能统一被发现、注册、调用、管理,因此设计了 SystemAbility Manager(SAMgr)

它的核心使命只有一句:

让系统的每个能力都有“身份证”,统一注册、统一发现、统一通信。

1.2 SAMgr 的五个关键词

关键词 说明
统一注册 所有系统服务(System Ability, SA)都向 SAMgr 注册一个唯一 ID。
跨进程通信 通过 Binder/IPC 通道访问远端 SA。
按需加载 只有被调用时才真正加载,减少开机占用。
多实例模型 同一能力可在不同设备实例化(分布式)。
生命周期托管 SAMgr 负责启动、重启、卸载。

二、系统服务的架构总览

┌───────────────────────────────┐
│           应用 / Framework层   │
│   Context.getSystemAbility(id) │
└───────────▲────────────────────┘
            │
    IPC / Binder 调用
            │
┌───────────┴────────────────────┐
│     SystemAbilityManager (SAMgr)│
│  ├── ServiceRegistry (注册表)   │
│  ├── Loader(动态加载器)         │
│  ├── SA Record/Stub 管理        │
│  └── 生命周期/守护线程          │
└───────────▲────────────────────┘
            │
            │ 通过 so/sa 子系统加载
            ▼
┌───────────────────────────────┐
│     SystemAbility Service进程 │
│  ├── OnStart / OnStop          │
│  ├── IPC Stub / Proxy          │
│  └── SA Base Class             │
└───────────────────────────────┘

三、SAMgr 机制详解:服务注册 → 发现 → 调用

3.1 服务注册(Service Registration)

系统能力分为:

  • 静态 SA(系统启动时注册)
  • 动态 SA(按需加载)

注册信息来源于:

  • services/systemability/sa_profile 配置(系统核心);
  • 或自定义的 .sa 配置文件(供扩展服务使用)。

核心注册 API(C/C++):

#include "system_ability_definition.h"
#include "system_ability_manager.h"

sptr<ISystemAbilityManager> saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
int32_t SA_ID = 3401; // 自定义服务ID
sptr<IRemoteObject> myService = new (std::nothrow) MyServiceStub();
saMgr->AddSystemAbility(SA_ID, myService);

每个服务都由一个 唯一 SA ID(int32_t) 标识,系统内由 system_ability_definition.h 定义。

3.2 服务发现(GetSystemAbility)

任何客户端都可以通过 GetSystemAbility(id) 获取服务:

sptr<ISystemAbilityManager> saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remote = saMgr->GetSystemAbility(SA_ID);
sptr<IMyService> proxy = iface_cast<IMyService>(remote);
proxy->DoSomething();

如果目标服务尚未启动,SAMgr 会根据配置自动加载进程,再返回句柄。


四、系统服务加载与生命周期管理

4.1 生命周期阶段

阶段 说明
OnStart() 服务初始化、资源加载、线程创建。
OnAddSystemAbility() 被 SAMgr 注册后调用,可进行依赖服务发现。
OnStop() 服务退出清理。

示例:

#include "system_ability.h"
#include "system_ability_definition.h"

class HelloService : public SystemAbility {
    DECLARE_SYSTEM_ABILITY(HelloService);
public:
    HelloService(int32_t saId, bool runOnCreate)
        : SystemAbility(saId, runOnCreate) {}

    void OnStart() override {
        HILOGI("HelloService started");
        Publish(this); // 向 SAMgr 发布
    }
    void OnStop() override {
        HILOGI("HelloService stopped");
    }
};
REGISTER_SYSTEM_ABILITY_BY_ID(HelloService, 3401);

4.2 生命周期托管策略

  • 永久服务(RunOnCreate=true):开机启动。
  • 延迟加载服务:第一次 GetSystemAbility() 时加载。
  • 远程服务崩溃重启:SAMgr 监控 Binder 死亡并自动重启。
  • 依赖管理OnAddSystemAbility(id) 用于感知依赖的服务注册。

五、自定义系统服务实现与注册实战

5.1 实现一个简单服务

假设我们要做一个日志统计服务,提供 ReportEvent() 接口。

服务端:

// LogStatService.h
#include "system_ability.h"
#include "iremote_stub.h"

class ILogStat : public IRemoteBroker {
public:
    DECLARE_INTERFACE_DESCRIPTOR(u"ohos.demo.ILogStat");
    virtual void ReportEvent(const std::string& event) = 0;
};

// Stub 实现
class LogStatStub : public IRemoteStub<ILogStat> {
public:
    int OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption &option) override {
        if (code == 1) {
            std::string evt = data.ReadString();
            ReportEvent(evt);
            reply.WriteInt32(0);
            return 0;
        }
        return -1;
    }
};

// 服务本体
class LogStatService : public SystemAbility, public LogStatStub {
    DECLARE_SYSTEM_ABILITY(LogStatService);
public:
    LogStatService(int32_t id, bool runOnCreate)
        : SystemAbility(id, runOnCreate) {}

    void OnStart() override {
        HILOGI("LogStatService start");
        Publish(this); // 注册到 SAMgr
    }
    void ReportEvent(const std::string &event) override {
        HILOGI("Event reported: %{public}s", event.c_str());
    }
};
REGISTER_SYSTEM_ABILITY_BY_ID(LogStatService, 3401);

服务配置(profile/log_stat.sa):

{
  "name": "LogStatService",
  "systemAbilityId": 3401,
  "runOnCreate": true,
  "distributed": false,
  "dumpLevel": 1
}

5.2 客户端调用

#include "iservice_registry.h"
#include "iremote_proxy.h"

class LogStatProxy : public IRemoteProxy<ILogStat> {
public:
    explicit LogStatProxy(const sptr<IRemoteObject>& impl) : IRemoteProxy(impl) {}
    void ReportEvent(const std::string& event) override {
        MessageParcel data, reply;
        data.WriteInterfaceToken(GetDescriptor());
        data.WriteString(event);
        Remote()->SendRequest(1, data, reply, MessageOption());
    }
};

// 调用端
sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> remote = sam->GetSystemAbility(3401);
sptr<ILogStat> proxy = new LogStatProxy(remote);
proxy->ReportEvent("app_launch");

六、系统服务间的通信与分布式扩展

  • SAMgr 本质上是 进程间的 Binder 注册中心
  • 通过 SystemAbilityManagerClient,任何服务都能获取别的 SA 的代理。
  • 分布式场景下(跨设备):SystemAbilityManager 可与 Distributed Service Framework(DSF) 协同,让 SA 跨设备被发现与访问。

七、调试与常见问题

问题 解决方案
服务未启动 检查 .sa 文件路径与 systemAbilityId 是否注册到 profile。
GetSystemAbility 返回 null 服务未运行或权限策略阻止访问。
Binder 崩溃重启频繁 检查服务异常退出;SAMgr 会不断尝试拉起。
服务依赖顺序错乱 OnAddSystemAbility(id) 中监听依赖的注册事件。

八、核心思想一句话总结

SAMgr 把系统服务“标准化”:统一 ID,统一生命周期,统一通信。

开发者要写系统服务,不必自建守护进程,不必操心 binder 注册,只需继承 SystemAbility,在 OnStart()Publish() 自己即可被系统管理。


✅ 实践建议

  • foundation/systemabilitymgr/sa_profile 看官方服务例子;
  • 自定义 SA 时,合理规划 systemAbilityId 范围(一般 3000+ 为自定义);
  • 配合 hiviewdfx 打点日志,监控服务状态;
  • 若需跨设备共享能力,继续往上看 分布式服务框架(DMS/DSF)

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。