赞
踩
鸿蒙基于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服务包含两部份:服务端、子功能端,服务提供了子功能的接口有默认的接口和自定义子功能接口,子功能接口又包含了进程内接口与进程间接口。后续章节会一一进行说明。
#include <service.h>
#include <message.h>
#include <common.h>
typedef struct ExampleService {
INHERIT_SERVICE;
Identity identity;
} ExampleService;
#define INHERIT_SERVICE \
const char *(*GetName)(Service * service); \
BOOL (*Initialize)(Service * service, Identity identity); \
BOOL (*MessageHandle)(Service * service, Request * request); \
TaskConfig (*GetTaskConfig)(Service * service)
该宏定义了服务的生命周期函数的函数指针。
struct Identity {
/** Service ID */
int16 serviceId;
/** Feature ID */
int16 featureId;
/** Message queue ID */
MQueueId queueId;
};
该宏定义了服务ID、默认子功能ID及消息队列ID。
typedef void *MQueueId;
关于默认子功能及消息队列指针,此处按下不表,在相应部份再进行说明,此时服务结构定义只需要添加两个宏即可。
实现该服务对象指向的生命周期函数。
#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;
}
实例化ExampleService服务对象,将对象的生命函数指针指向其实现其实现的生命周期函数。
// 创建服务对象
static ExampleService g_example = {
.GetName = GetName,
.Initialize = Initialize,
.MessageHandle = MessageHandle,
.GetTaskConfig = GetTaskConfig,
{-1, -1, NULL}
};
identity初始化时serviceId,featureId均为-1,queueId为空,在生命周期函数Initialize中赋值系统分配的identity。
向SAMGR注册服务及接口
static void Init(void)
{
SAMGR_GetInstance()->RegisterService((Service *)&g_example);
}
定义服务的初始化入口:
SYSEX_SERVICE_INIT(Init);
通过以上操作后,服务驻存在系统中,服务没有对外的接口,此时需要添加子功能feature,提供服务对外的接口。
子功能按分为两类:进程内子功能、跨进程子功能
子功能按通信方式分为两类:进程内子功能、跨进程子功能。
子功能还可以分为服务默认子功能与自定义子功能。
默认子功能不需要子功能生命周期,其生命周期由服务的生命周期管理。
#include <iunknown.h>
typedef struct {
INHERIT_IUNKNOWN;
BOOL (*FeatureCall)(IUnknown *iUnknown, const char *buff);
} DefaultFeatureApi;
#include <iproxy_server.h>
typedef struct {
INHERIT_SERVER_IPROXY;
BOOL (*FeatureCall)(IUnknown *iUnknown, const char *buff);
} CrossProcessFeatureApi;
进程内子功能与跨进程子功能的声明表现在使用两个宏INHERIT_IUNKNOWN与INHERIT_SERVER_IPROXY
#define INHERIT_IUNKNOWN \
int (*QueryInterface)(IUnknown *iUnknown, int version, void **target); \
int (*AddRef)(IUnknown *iUnknown); \
int (*Release)(IUnknown *iUnknown)
#define INHERIT_SERVER_IPROXY \
INHERIT_IUNKNOWN; \
int32 (*Invoke)(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
跨进程feature的定义相对进程内定义,多出来的Invoke函数指针,跨进程的方法通过此方法完成进程间通信、参数序列化与反序列化。
默认子功能需要将声明放在服务结构中进行声明。
以2.1.1中声明的服务为例,只需要将DefaultFeatureApi或CrossProcessFeatureApi添加至服务ExampleService中。
// 默认进程内子功能
typedef struct ExampleService {
INHERIT_SERVICE;
INHERIT_IUNKNOWNENTRY(DefaultFeatureApi);
Identity identity;
} ExampleService;
// 自定义跨进程子功能
typedef struct ExampleService {
INHERIT_SERVICE;
INHERIT_IUNKNOWNENTRY(CrossProcessFeatureApi);
Identity identity;
} ExampleService;
INHERIT_IUNKNOWNENTRY宏添加了子功能的版本也引用计数,定义在foundation\systemabilitymgr\samgr_lite\interfaces\kits\samgr\iunknown.h
#define INHERIT_IUNKNOWNENTRY(T) \
uint16 ver; \
int16 ref; \
T iUnknown
首先自定义子功能结构,然后定义子功能接口ExampleFeatureApi,子功能接口也分为进程间接口与跨进程接口。
// 定义子功能结构
typedef struct ExampleFeature {
INHERIT_FEATURE;
INHERIT_IUNKNOWNENTRY(ExampleFeatureApi);
Identity identity;
} ExampleFeature;
#include <iunknown.h>
typedef struct {
INHERIT_IUNKNOWN;
BOOL (*FeatureCall)(IUnknown *iUnknown, const char *buff);
} ExampleFeatureApi;
#include <iproxy_server.h>
typedef struct {
INHERIT_SERVER_IPROXY;
BOOL (*FeatureCall)(IUnknown *iUnknown, const char *buff);
} ExampleFeatureApi;
#define INHERIT_FEATURE \
const char *(*GetName)(Feature *feature); \
void (*OnInitialize)(Feature *feature, Service *parent, Identity identity); \
void (*OnStop)(Feature *feature, Identity identity); \
BOOL (*OnMessage)(Feature *feature, Request *request); \
BOOL (*IsDistributed)(void)
该宏定义了子功能的生命周期函数的函数指针。
static BOOL FeatureCall(IUnknown *iUnknown, const char *buff)
{
(void)iUnknown;
HILOG_INFO(1,"buff:%s\n", buff);
HILOG_INFO(1,"[LPC Test][SyncCall API] Default Success!\n");
return TRUE;
}
enum MessageId {
MSG_PROC,
MSG_TIME_PROC,
};
static BOOL FeatureCall(IUnknown *iUnknown, const char *body)
{
Request request = {.msgId = MSG_PROC, .msgValue = 0};
request.len = (uint32_t)(strlen(body) + 1);
request.data = malloc(request.len);
if (request.data == NULL) {
return FALSE;
}
if (strcpy_s(request.data, request.len, body) != EOK) {
free(request.data);
return FALSE;
}
ExampleFeature *feature = GET_OBJECT(iUnknown, ExampleFeature, iUnknown);
return SAMGR_SendRequest(&g_example.identity, &request, NULL);
}
FeatureCall由跨进程方法Invoke调用,然后子功能通过SAMGR_SendRequest发送请求至内核。
默认子功能不需要子功能生命周期,实现子功能对象指向的生命周期函数。
#define EXAMPLE_FEATURE "modulefeature"
enum MessageId {
MSG_PROC,
MSG_TIME_PROC,
};
static const char *FEATURE_GetName(Feature *feature)
{
(void)feature;
return EXAMPLE_FEATURE;
}
static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity)
{
ExampleFeature *demoFeature = (ExampleFeature *)feature;
demoFeature->identity = identity;
printf("serviceId:%d,featureId:%d,queueId:%p\n", identity.serviceId, identity.featureId, identity.queueId);
printf("demoFeature:%p,g_example:%p\n", demoFeature, &g_example);
printf("serviceId:%d,featureId:%d,queueId:%p\n",
g_example.identity.serviceId, g_example.identity.featureId, g_example.identity.queueId);
}
static void FEATURE_OnStop(Feature *feature, Identity identity)
{
(void)feature;
(void)identity;
g_example.identity.queueId = NULL;
g_example.identity.featureId = -1;
g_example.identity.serviceId = -1;
}
static BOOL FEATURE_OnMessage(Feature *feature, Request *request)
{
(void)feature;
if (request->msgId == MSG_PROC) {
printf("[LPC Test][OnMessage: S:%s, F:%s] msgId<MSG_PROC> %s \n",
EXAMPLE_SERVICE, feature->GetName(feature),
(char *)request->data);
Response response = {.data = "Yes, you did!", .len = 0};
SAMGR_SendResponse(request, &response);
return TRUE;
} else {
if (request->msgId == MSG_TIME_PROC) {
printf("[LPC Test] OnMessage: S:%s, F:%s] Time Message Get Value<%s>!",
EXAMPLE_SERVICE, feature->GetName(feature),
request->msgValue ? "TRUE" : "FALSE");
// AsyncTimeCall(GET_IUNKNOWN(g_example));
return FALSE;
}
}
printf("[LPC Test][OnMessage S:%s, F:%s] Inner Error! \n",
EXAMPLE_SERVICE, feature->GetName(feature));
return FALSE;
}
FEATURE_OnMessage处理异步处理应答的消息。
static ExampleFeature g_example = {
.GetName = FEATURE_GetName,
.OnInitialize = FEATURE_OnInitialize,
.OnStop = FEATURE_OnStop,
.OnMessage = FEATURE_OnMessage,
DEFAULT_IUNKNOWN_ENTRY_BEGIN,
.FeatureCall = FeatureCall,
DEFAULT_IUNKNOWN_ENTRY_END,
.identity = {-1, -1, NULL},
};
static ExampleFeature g_example = {
.GetName = FEATURE_GetName,
.OnInitialize = FEATURE_OnInitialize,
.OnStop = FEATURE_OnStop,
.OnMessage = FEATURE_OnMessage,
SERVER_IPROXY_IMPL_BEGIN,.
.Invoke = Invoke,
.FeatureCall = FeatureCall,
IPROXY_END,
.identity = {-1, -1, NULL},
};
// foundation\systemabilitymgr\samgr_lite\interfaces\kits\samgr\iunknown.h
#define DEFAULT_VERSION 0x20
#define DEFAULT_IUNKNOWN_IMPL \
.QueryInterface = IUNKNOWN_QueryInterface, \
.AddRef = IUNKNOWN_AddRef, \
.Release = IUNKNOWN_Release
#define IUNKNOWN_ENTRY_BEGIN(version) \
.ver = (version), \
.ref = 1, \
.iUnknown = { \
DEFAULT_IUNKNOWN_IMPL
#define DEFAULT_IUNKNOWN_ENTRY_BEGIN IUNKNOWN_ENTRY_BEGIN(DEFAULT_VERSION)
#define DEFAULT_IUNKNOWN_ENTRY_END IUNKNOWN_ENTRY_END
此宏表示实现接口查询与引用计数方法使用系统实现的IUNKNOWN_QueryInterface、IUNKNOWN_AddRef、IUNKNOWN_Release三个方法。
// foundation\systemabilitymgr\samgr_lite\interfaces\kits\registry\iproxy_server.h
#define SERVER_PROXY_VER 0x80
#define SERVER_IMPL_PROXY_VER ((uint16)SERVER_PROXY_VER | (uint16)DEFAULT_VERSION)
#define SERVER_IPROXY_IMPL_BEGIN IUNKNOWN_ENTRY_BEGIN(SERVER_IMPL_PROXY_VER)
#define IPROXY_END IUNKNOWN_ENTRY_END
此宏表示实现接口查询与引用计数方法使用系统实现的IUNKNOWN_QueryInterface、IUNKNOWN_AddRef、IUNKNOWN_Release三个方法。
两个宏校验的版本号不同。
在跨进程子功能中,需要实现Invoke接口。
typedef enum {
FEATURE_CALL,
MY_MODULE_ASYNC_CALLBACK,
} MyModuleMsgID;
static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
{
ExampleFeatureApi *api = (ExampleFeatureApi *)iProxy;
ExampleFeature *feature = GET_OBJECT(api, ExampleFeature, iUnknown);
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxx api:%p,g_example:%p,feature:%p\n", api, &g_example, feature);
BOOL ret;
size_t tempLen = 0;
size_t len = 0;
switch (funcId) {
case FEATURE_CALL:
buf = ReadString(req, &tempLen);
printf("[feature] tempLen:%u\n", tempLen);
printf("[feature] req: %s\n", buf);
break;
default:
WriteBool(reply, FALSE);
break;
}
return 0;
}
默认子功能的注册在服务注册之后。
static void Init(void)
{
SAMGR_GetInstance()->RegisterService((Service *)&g_example);
SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(g_example));
}
SYSEX_SERVICE_INIT(Init);
static void Init(void)
{
SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, (Feature *)&g_example);
SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
printf("[Register Test][Reg S:%s, F:%s]!\n",EXAMPLE_SERVICE, EXAMPLE_FEATURE);
}
SYSEX_FEATURE_INIT(Init);
修改文件base\security\permission_lite\services\ipc_auth\include\policy_preset.h
FeaturePolicy mymoduleFeature[] = {
{
"modulefeature",
{
{
.type = RANGE,
.uidMin = 0,
.uidMax = __INT_MAX__,
},
},
},
};
// 在g_presetPolicies[]里面增加
{"moduleservice", mymoduleFeature, 1},
注意,服务名“moduleservice"与子功能名"modulefeature”,长度最长15个字节。
#include <iunknown.h>
static DefaultFeatureApi *g_defaultProxy;
IUnknown *iUnknown1 = SAMGR_GetInstance()->GetDefaultFeatureApi(EXAMPLE_SERVICE);
if (iUnknown1 == NULL) {
return -1;
}
int32_t ret = iUnknown1->QueryInterface(iUnknown1, DEFAULT_VERSION, (void **)&g_defaultProxy);
if (ret != 0 || g_defaultProxy == NULL) {
return -1;
}
ret = g_defaultProxy->FeatureCall((IUnknown *)g_defaultProxy, "Hi L1 first SA");
if (ret != 0) {
return -1;
}
ret = g_defaultProxy->Release((IUnknown *)g_defaultProxy);
#include <iunknown.h>
typedef struct {
int result;
size_t messageLen;
uint8_t *message;
} ServiceRspMsg;
static CrossProcessFeatureApi *g_clientProxy;
IUnknown *iUnknown2 = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
if (iUnknown2 == NULL) {
return -1;
}
int32_t ret = iUnknown2->QueryInterface(iUnknown2, CLIENT_PROXY_VER, (void **)&g_clientProxy);
if (ret != 0 || g_clientProxy == NULL) {
return -1;
}
IpcIo request;
char data[250];
IpcIoInit(&request, data, sizeof(data), 0);
WriteString(&request, "I want to async call good result!");
ServiceRspMsg reply = { 0 };
ret = g_clientProxy->Invoke((IUnknown *)g_clientProxy, FEATURE_CALL, &request, NULL, NULL);
if (ret != EXAMPLE_SUCCESS) {
printf("[AsyncCall] ret:%d\n\r", ret);
}
if (ret != 0) {
return -1;
}
ret = g_clientProxy->Release((IUnknown *)g_defaultProxy);
执行步骤:g_clientProxy->Invoke---------->异步FeatureCall方法---------->SAMGR_SendRequest---------->FEATURE_OnMessage---------->(IPCRPC)---------->服务Invoke
// 序列化
IpcIo request;
char data[250];
IpcIoInit(&request, data, sizeof(data), 0);
WriteString(&request, "I want to async call good result!");
// 反序列化
buf = ReadString(req, &tempLen);
typedef int (*AsyncHandlerFunc)(IOwner owner, int code);
static int CurrentCallback(IOwner owner, int code, IpcIo *reply)
{
struct CurrentNotify *notify = (struct CurrentNotify *)owner;
int32_t ret;
ReadUint32(reply, &ret);
printf("CurrentCallback................ %d\n", ret);
notify->handler(notify->data, ret);
return 0;
}
struct CurrentNotify {
IOwner data;
AsyncHandlerFunc handler;
};
......
ReplyData dataReply;
dataReply.id = 55;
IOwner notify = &dataReply; //自定义结构体
struct CurrentNotify customData = {
.data = notify,
.handle = AsyncHandler
};
ret = g_clientProxy->Invoke((IUnknown *)g_clientProxy, MY_MODULE_ASYNC_CALLBACK, &request, &customData, CurrentCallback);
if (ret != 0) {
printf("[AsyncCallBack] ret:%d\n\r", ret);
}
static BOOL AsyncCallBack(IUnknown *iUnknown, const char *body, Handler handler)
{
Request request = {.msgId = MSG_PROC, .msgValue = 0};
request.len = (uint32_t)(strlen(body) + 1);
request.data = malloc(request.len);
if (request.data == NULL) {
return FALSE;
}
if (strcpy_s(request.data, request.len, body) != EOK) {
free(request.data);
return FALSE;
}
// ExampleFeature *feature = GET_OBJECT(iUnknown, ExampleFeature, iUnknown);
printf("[LPC Test][AsyncCallBack API] Send request! \n");
return SAMGR_SendRequest(&g_example.identity, &request, handler);
}
static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
{
ExampleFeatureApi *api = (ExampleFeatureApi *)iProxy;
ExampleFeature *feature = GET_OBJECT(api, ExampleFeature, iUnknown);
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxx api:%p,g_example:%p,feature:%p\n", api, &g_example, feature);
BOOL ret;
size_t tempLen = 0;
uint8_t *buf = NULL;
switch (funcId) {
case FEATURE_CALL:
buf = ReadString(req, &tempLen);
printf("[feature] tempLen:%u\n", tempLen);
printf("[feature] req: %s\n", buf);
break;
case MY_MODULE_ASYNC_CALLBACK: { // convert to sync proxy
buf = ReadString(req, &tempLen);
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxx buf:%s\n", buf);
WriteUint32(reply, 1);
break;
default:
WriteBool(reply, FALSE);
break;
}
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。