鸿蒙linux内核的L1设备服务开发详解
鸿蒙基于linux内核的L1设备的系统基于面向服务架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务进程、进程间服务调用的开发能力。现对此基座下的服务进行剖析并以实例方式进行讲解。
一、简介
在L1设备中服务分为两类:
-
core system service
foundation\systemabilitymgr\safwk_lite\BUILD.gn
deps添加依赖,由foundation进程启动加载。此种方式的服务挂载在foundation进程中。
-
system and application service
以应用的方式进行启动,可以在/base/startup/init/service/etc/init.cfg中添加start service方式启动,或者以可执行程序的方式进行启动。此种方式的服务是以本身的进程启动。
二、服务的开发
首先SA服务包含两部份:服务端、子功能端,服务提供了子功能的接口有默认的接口和自定义子功能接口,子功能接口又包含了进程内接口与进程间接口。后续章节会一一进行说明。
2.1 服务端实现
2.1.1 服务声明
#include <service.h>
#include <message.h>
#include <common.h>
typedef struct ExampleService {
INHERIT_SERVICE;
Identity identity;
} ExampleService;
- INHERIT_SERVICE在foundation\systemabilitymgr\samgr_lite\interfaces\kits\samgr\service.h中定义如下:
#define INHERIT_SERVICE \
const char *(*GetName)(Service * service); \
BOOL (*Initialize)(Service * service, Identity identity); \
BOOL (*MessageHandle)(Service * service, Request * request); \
TaskConfig (*GetTaskConfig)(Service * service)
该宏定义了服务的生命周期函数的函数指针。
- Identity在foundation\systemabilitymgr\samgr_lite\interfaces\kits\samgr\message.h中定义如下:
struct Identity {
/** Service ID */
int16 serviceId;
/** Feature ID */
int16 featureId;
/** Message queue ID */
MQueueId queueId;
};
该宏定义了服务ID、默认子功能ID及消息队列ID。
- MQueueId定义在foundation\industrialbus\modules\common.h
typedef void *MQueueId;
关于默认子功能及消息队列指针,此处按下不表,在相应部份再进行说明,此时服务结构定义只需要添加两个宏即可。
2.1.2 实现服务的生命周期函数
实现该服务对象指向的生命周期函数。
- 服务生命周期函数,实现示例如下:
#define EXAMPLE_SERVICE "moduleservice"
// 返回服务名称
static const char *GetName(Service *service)
{
(void)service;
return EXAMPLE_SERVICE;
}
// 初始化服务
static BOOL Initialize(Service *service, Identity identity)
{
ExampleService *example = (ExampleService *)service;
// 保存服务的唯一身份标识,用来自己的IUnknown接口对服务发消息时使用。
example->identity = identity;
return TRUE;
}
static BOOL MessageHandle(Service *service, Request *msg)
{
ExampleService *example = (ExampleService *)service;
(void)example;
switch (msg->msgId) {
default:break;
}
return FALSE;
}
static TaskConfig GetTaskConfig(Service *service)
{
(void)service;
TaskConfig config = {
LEVEL_HIGH, PRI_NORMAL,
0x800, MODULE_QUEUE_SIZE, SINGLE_TASK};
return config;
}
2.1.3 创建服务对象
实例化ExampleService服务对象,将对象的生命函数指针指向其实现其实现的生命周期函数。
// 创建服务对象
static ExampleService g_example = {
.GetName = GetName,
.Initialize = Initialize,
.MessageHandle = MessageHandle,
.GetTaskConfig = GetTaskConfig,
{
-1, -1, NULL}
};
identity初始化时serviceId,featureId均为-1,queueId为空,在生命周期函数Initialize中赋值系统分配的identity。
2.1.4 注册服务
向SAMGR注册服务及接口
static void Init(void)
{
SAMGR_GetInstance()->RegisterService((Service *)&g_example);
}
定义服务的初始化入口:
SYSEX_SERVICE_INIT(Init);
2.2 子功能端
通过以上操作后,服务驻存在系统中,服务没有对外的接口,此时需要添加子功能feature,提供服务对外的接口。
子功能按分为两类:进程内子功能、跨进程子功能
2.2.1 定义子功能
子功能按通信方式分为两类:进程内子功能、跨进程子功能。
子功能还可以分为服务默认子功能与自定义子功能。
默认子功能不需要子功能生命周期,其生命周期由服务的生命周期管理。
2.2.1.1 进程内子功能接口
#include <iunknown.h>
typedef struct {
INHERIT_IUNKNOWN;
BOOL (*FeatureCall)(IUnknown *iUnknown, const char *buff);
} DefaultFeatureApi;
2.2.1.2 跨进程子功能接口
#include <iproxy_server.h>
typedef struct {
INHERIT_SERVER_IPROXY;
BOOL (*FeatureCall)(IUnknown *iUnknown, const char *buff);
} CrossProcessFeatureApi;
进程内子功能与跨进程子功能的声明表现在使用两个宏INHERIT_IUNKNOWN与INHERIT_SERVER_IPROXY
- INHERIT_IUNKNOWN定义在foundation\systemabilitymgr\samgr_lite\interfaces\kits\samgr\iunknown.h
#define INHERIT_IUNKNOWN \
int (*QueryInterface)(IUnknown *iUnknown, int version, void **target); \
int (*AddRef)(IUnknown *iUnknown); \
int (*Release)(IUnknown *iUnknown)
- INHERIT_SERVER_IPROXY定义在foundation\systemabilitymgr\samgr_lite\interfaces\kits\samgr\iunknown.h
#define INHERIT_SERVER_IPROXY \
INHERIT_IUNKNOWN; \
int32 (*Invoke)(IServerProxy <