OpenHarmony系统服务框架SAMGR解析

OpenHarmony中SAMGR服务框架简介。

Views: 25
0 0
Read Time:3 Minute, 29 Second

最近在开发鸿蒙座舱的过程中,原本以为其整个系统只是基于AOSP进行魔改,提供除ART之外的容器运行能力。但仔细研究了一下其系统服务的实现机制,发现其系统服务的管理存在独立于安卓原生ServiceManager之外的一套框架,即SAMGR。需要说明的是,OpenHarmony本身适配多种系统(A核对应标准系统,M核对应轻量系统),在本文中所对应的为标准系统。

在安卓系统中,系统服务框架基于ServiceManager。以Native服务为例,要注册发布一个服务涉及到启动配置(rc)、以及代码上的继承实现。通常分为以下几步:

//rc配置
service evs_app /system/bin/evs_app
    class hal
    priority -20
    user automotive_evs
    group automotive_evs
    disabled
on late-init
    start evs_app

//代码实现
1.Main函数中配置binder线程池
hardware::configureRpcThreadpool(5, /*willjoin*/ false);
2.Main函数中初始化binder通信基础
sp<ProcessState> proc(ProcessState::self());
3.Main函数中获取ServiceManager,与ServiceManager建立连接
sp<IServiceManager> sm = defaultServiceManager();
4.Main函数中进行服务发布
xxxxService::instantiate();
5.启动与加入线程池
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();

而在OpenHarmony系统中,系统服务框架为SAMGR,也就是SystemAbility Manager。其与安卓系统的ServiceManager存在很大的区别,主要的差异点包括:

1.开发者不再需要实现Main函数,服务启动统一由sa_mian进行加载

2.开发者需要实现固定的接口,并将其编译为共享库,sa_main将通过dlopen的方式进行加载

3.每个服务都需要额外的配置文件,sa_main负责解析并依据配置进行启动

服务实现

在鸿蒙系统的SAMGR服务框架中,服务实现的逻辑其实与安卓有相似之处,通过继承公有类的方式重载实现自身的逻辑。具体实现细节参考如下:

头文件实现:

//MyService.h
//以下头文件来自于OpenHarmony OS
#include "singleton.h"
#include "iremote_object.h"
#include "system_ability.h"
#include "ipc_object_stub.h"

class MyService : public OHOS::SystemAbility, public OHOS::IPCObjectStub, public OHOS::IRemoteObject::DeathRecipient, public OHOS::DelayedRefSingleton< MyService > 
{
         //构造函数&虚构函数
MyService(int32_t systemAbilityId = 5002, bool runOnCreate = true);
         virtual ~ MyService ();
         
        //单例实现
        static MyService& GetInstance()
        {
            return DelayedRefSingleton< MyService>::GetInstance();
        }

        //继承自公有类的接口
        std::string GetClassName() override;
        void OnDump() override;
        //服务启动
        void OnStart() override;
       //服务终止
        void OnStop() override;
        void OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> &object) override;
}

源文件实现:

//MyService.cpp
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <linux/audit.h>
#include "log.h"
#include "MyService.h"

#define LOG_TAG " MyService"

using namespace std;
using namespace OHOS;

// Static function for pthread
static void* InitThreadFunc(void* arg)
{
    MyService* self = static_cast< MyService*>(arg);
    self->init();
    return nullptr;
}
//构造函数
//需要注意这里的systemAbilityId与xml中配置的需要保持一致
MyService::MyService(int32_t systemAbilityId, bool runOnCreate) : SystemAbility(systemAbilityId, runOnCreate), IPCObjectStub(OHOS::to_utf16("MyService"))
{
    HILOGI(LOG_TAG, " MyService constructor called, saId=%{public}d, runOnCreate=%{public}d", systemAbilityId, runOnCreate);
}
//析构函数
MyService::~ MyService() 
{

}

//重要,必须实现
std::string MyService::GetClassName()
{
    return "MyService";
}


void MyService::OnDump()
{
    HILOGI(LOG_TAG, "MyService OnDump");
}

void MyService::init(void) 
{
    HILOGI(LOG_TAG, "MyService::init() called, entering loop");
    while(1)
    {
        //服务循环体
    }
}

void MyService::OnStart()
{
    OHOS::SystemAbility::OnStart();
    
    sptr<OHOS::IRemoteObject> remoteObject = this;
    bool result = Publish(remoteObject);
    if (!result) {
        HILOGE(LOG_TAG, " MyService start failed! Publish returned false");
        return;
    }
    
    // Start init() in a separate thread to avoid blocking OnStart()
    pthread_t threadId;
    int ret = pthread_create(&threadId, nullptr, InitThreadFunc, this);
    if (ret != 0) {
        HILOGE(LOG_TAG, "Failed to create init thread, error: %{public}d", ret);
    } else {
        HILOGI(LOG_TAG, "Init thread created successfully");
        pthread_detach(threadId);
    }
}

//重载实现onStop
void MyService::OnStop()
{
    HILOGI(LOG_TAG, " MyService OnStop");
    OHOS::SystemAbility::OnStop();
}

//重载实现onRemoteDied
Void MyService::OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> &object)
{
    (void)object;
    HILOGW(LOG_TAG, "OnRemoteDied.");
}

// Register SystemAbility when library is loaded
// This is called automatically when the library is loaded by sa_main
REGISTER_SYSTEM_ABILITY_BY_ID(MyService, 5002, true);

服务配置

在服务配置上,SAMGR还需要一份配置文件,以便让sa_main在启动阶段知道加载对应的共享库。在OHOS系统中,这份配置文件以xml形式存在,放置在/system/profile/目录下,其内容大体如下(注:不同OpenHarmony版本存在差异):

<?xml version="1.0" encoding="utf-8"?>
<info>
    <process>vhssrv</process>
    <loadlibs>
        <libpath>libvhssrv.z.so</libpath>
    </loadlibs>
    <systemability>
        <name>2654</name>
        <libpath>libvhssrv.z.so</libpath>
        <run-on-create>true</run-on-create>
        <distributed>false</distributed>
        <dump-level>1</dump-level>
    </systemability>
</info>

在这份xml配置中,process标签用于表明该服务的进程名,libpath标签用于表明sa_main启动服务时需要加载的动态库,而SystemAbility标签则用于对该系统服务进行更细致的控制。

<name>标签用于表明该SA ID,这是SystemAbility服务中的唯一ID标识;该ID在我们实现服务时需要匹配;

<libpath>标签用于表明该SA的动态库路径;

<run-on-create>标签用于表明该SA是否自启动,true即代表需要自启动,false则无需自启动;

<distributed>标签用于表明该SA是否支持分布式访问;

<dump-level>标签用于配置管理和调试权限;

同时,我们在rc启动配置中需要对sa_main的启动进行显式说明,如下所示:

service sai-daemon  /system/bin/sa_main  /system/profile/sai_daemon.xml
    class core
    user root
    group root
    seclabel u:r:su:s0

这里sai-daemon服务,就是通过sa_main读取/system/profile/sai_daemon.xml中的配置,从而将服务注册到SAMGR中。

服务获取

当我们的服务启动后,我们如何在其他的进程中(Client)获取该服务并建立连接呢。

简单来说,Client可使用 SystemAbilityManagerClient 获取 SystemAbilityManager 实例,然后调用 GetSystemAbility 获取服务的代理对象(IRemoteObject)。

#include "isystem_ability_manager.h"
#include "if_system_ability_manager.h"
#include "iservice_registry.h"

// 1. 获取 SystemAbilityManager 单例实例
sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sam == nullptr) {
    // 处理获取失败逻辑
    return;
}

// 2. 指定想要获取的 SA 的 ID (例如:SAMPLE_SERVICE_ID)
int32_t systemAbilityId = 1234; 

// 3. 向 SAMGR 获取服务代理对象
sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(systemAbilityId);
if (remoteObject == nullptr) {
    // 处理找不到服务逻辑
    return;
}

// 4. 将 remoteObject 转换为具体的服务代理类(如 ISampleService)
// sptr<ISampleService> serviceProxy = iface_cast<ISampleService>(remoteObject);

Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

文章: 101

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注

zh_CNCN