前言
在刚接触 Samgr 时笔者根本不知道其设计初衷是啥(水平较菜,刚接触C语言),尽管官方文档对其进行了介绍,但仍有种听君一席话胜读一席话的感觉。为此,笔者花了一天对其进行探究和学习,将笔记梳理并记录于本文。
参考博文
《鸿蒙子系统解读-分布式任务调度篇(上)》
《鸿蒙OS开源代码精要解读之—— 系统服务框架子系统(服务启动)》
《深入浅出OpenHarmony架构》
Samgr概念
官方说明
官方仓 https://gitee.com/openharmony/distributedschedule_samgr_lite 对其解释如下:
由于平台资源有限,且硬件平台多样,因此需要屏蔽不同硬件架构和平台资源的不同、以及运行形态的不同,提供统一化的系统服务开发框架。根据RISC-V、Cortex-M、Cortex-A不同硬件平台,分为两种硬件平台,以下简称M核、A核。
-
M核:处理器架构为Cortex-M或同等处理能力的硬件平台,系统内存一般低于512KB,无文件系统或者仅提供一个可有限使用的轻量级文件系统,遵循CMSIS接口规范。
-
A核:处理器架构为Cortex-A或同等处理能力的硬件平台,内存资源大于512KB,文件系统完善,可存储大量数据,遵循POSIX接口规范。
系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。其中:
- M核:包含服务开发、服务的子功能开发、对外接口的开发以及多服务共进程的开发框架。
- A核:在M核能力基础之上,包含了进程间服务调用、进程间服务调用权限控制、进程间服务接口的开发等能力。
面向服务的架构:
- Provider:服务的提供者,为系统提供能力(对外接口)。
- Consumer:服务的消费者,调用服务提供的功能(对外接口)。
- Samgr:作为中介者,管理Provider提供的能力,同时帮助Consumer发现Provider的能力。
系统服务开发框架主体对象:
个人理解
参考了一些资料后,发现一切皆服务的思想,与 Spring 中 Bean 类似,通过一种约定的封装方式调用相关类或者方法。增强了项目的扩展性,同时屏蔽底层实现,只关心接口。例如,可以通过获取serviceName 获取一个服务 service,并调用其接口相关方法。该 service 可以是从本地调用,也可以是从远程调用。
- 如果进行本地调用,只需要在使用前,将 service 存入一个本地缓存中。调用时从缓存中找出该 service 即可,此为直接调用。本地调用也能通过消息机制实现异步调用
- 如果进行远程调用,则需通过 RPC 实现,在 OHOS 中应该是 LiteIPC
当意识到上述问题时,笔者对整个 samgr 的梳理就很顺畅了
实例
参考资料的过程中,相关例子太少,都是开门见山地深入源码,对于笔者这种基础比较差的,着实看得痛苦。因此,在介绍具体细节前,找个本地直接调用的例子说明一下。(简化了代码,代码摘自《深入浅出OpenHarmony架构》)
服务注册
服务的注册分为以下几个步骤
1 . 实现 Service 接口
2 . 创建静态对象
3 . 注册服务和缺省特性
static void Init(void)
{
SAMGR_GetInstance()->RegisterService((Service *)&g_example);
SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE,GET_IUNKNOWN(g_example));
}
SYSEX_SERVICE_INT(Init);
4 . 实现 Feature 接口
5 . 注册 Feature
static void Init(void)
{
SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE,(Feature*)&g_example);
SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE,EXAMPLE_FEATURE,GET_IUNKNOWN(g_example));
}
SYSEX_FEATURE_INIT(Init);
服务发现
服务/特性完成注册后,使用者可以通过SAMGR接口获取具体接口并进行调用
DemoApi *demoApi = NULL;
IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE,EXAMPLE_FEATURE);
if(iUnknown == NULL){
return NULL;
}
int result = iUnknown->QueryInterface(iUnknown,DEFAULT_VERSION,(void **)&demoApi);
if(result !=0 || demoApi == NULL){
return NULL;
}
若能发现对应接口,则赋值给demoApi,故可进行对应接口 xxFunction 的调用
if(demoApi->xxFunction == NULL){
return NULL;
}
demoApi->