往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- OpenHarmony轻量系统服务管理|系统功能的存储机制详解(一)
- OpenHarmony轻量系统服务管理|系统功能的存储机制详解(二)
- OpenHarmony轻量系统服务管理|系统功能的存储机制详解(三)
- OpenHarmony轻量系统服务管理|进程间通信的核心机制详解(一)
- OpenHarmony轻量系统服务管理|进程间通信的核心机制详解(二)
- OpenHarmony轻量系统服务管理|进程间通信的核心机制详解(三)
- OpenHarmony轻量系统服务管理|进程间通信的核心机制详解(四)
- OpenHarmony轻量系统服务管理|进程间通信的核心机制详解(五)
- OpenHarmony轻量系统服务管理|进程间通信的核心机制详解(六)
- OpenHarmony轻量系统服务管理|客户代理的工厂模式机制详解
- OpenHarmony轻量系统服务管理|进程间通信的客户端代理详解(一)
- OpenHarmony轻量系统服务管理|进程间通信的客户端代理详解(二)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(一)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(二)
- 持续更新中……
函数实现详解
相关代码位于distributedschedule_samgr_lite\samgr_server\source\samgr_server.c
。
SamgrServer消息处理函数
//SamgrServer服务的消息处理函数,当前只实现了MSG_CLEAN,用于删除对应的ListNode
static BOOL MessageHandle(Service *service, Request *request)
{
SamgrServer *server = (SamgrServer *)service;
switch (request->msgId) {
case MSG_CLEAN: //消息ID为清除
MUTEX_Lock(server->mtx);
//根据pid删除对应的ListNode,并更新maps
SASTORA_ClearByPid(&server->store, request->msgValue);
MUTEX_Unlock(server->mtx);
break;
default:
break;
}
return TRUE;
}
获取服务的默认配置
//获取服务的任务配置,此时返回的是默认的任务配置
static TaskConfig GetTaskConfig(Service *service)
{
(void)service;
//默认的任务配置
TaskConfig config = {LEVEL_HIGH, PRI_BUTT - 1, 0x400, 20, SINGLE_TASK}; // Cannot use PRI_BUTT directly, so minus 1
return config;
}
资源请求处理函数
//根据不同的资源类型调用不同的处理函数
static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
{
//获取SamgrServer对象
SamgrServer *server = GET_OBJECT(iProxy, SamgrServer, iUnknown);
//读取一个uint32的值,赋给resource,即资源类型
int32 resource = IpcIoPopUint32(req);
//读取一个uint32的值,赋给option,即操作类型
int32 option = IpcIoPopUint32(req);
//参数检查,参数不合法则返回EC_INVALID
if (server == NULL || resource >= RES_BUTT || resource < 0 || g_functions[resource] == NULL) {
HILOG_ERROR(HILOG_MODULE_SAMGR, "Invalid Msg<%d, %d, %d>", resource, option, funcId);
return EC_INVALID;
}
//根据资源类型调用不同的处理函数
return g_functions[resource](server, option, origin, req, reply);
}
处理资源类型为endpoint的消息
/*
函数功能:处理endpoint类型的消息,注册endpoint
函数参数:@server:SamgrServer对象
@option:操作类型
@origin:请求数据
@req:请求IO
@reply:响应IO
函数返回:成功 返回EC_SUCCESS,失败 返回EC_FAILURE
函数描述:处理资源类型为RES_ENDPOINT和操作类型为OP_POST的请求消息,将其他进程的endpoint信息注册到satore中。
首先从请求消息中获取待注册的endpoint所属的进程ID号,然后在satore中查询是否存在注册记录。
若存在,则将pid对应的PidHandle对象的handle作为响应数据发送给请求者。
若不存在,则创建新的PidHandle对象保存待注册的endpoint的信息,然后添加到satore中。同样,将handle作为响应数据发送给请求者。
*/
static int ProcEndpoint(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply)
{
if (option != OP_POST) {
//若操作类型不为POST,则消息有误。发送响应消息,值为INVALID_INDEX
IpcIoPushUint32(reply, (uint32)INVALID_INDEX);
return EC_FAILURE;
}
//获取origin中记录的发送者processID值,processID由内核填充
pid_t pid = GetCallingPid(origin);
PidHandle handle;
MUTEX_Lock(server->mtx);
//根据进程ID在store的maps中查找对应的PidHandle,由handle返回,并返回其对应的下标
int index = SASTORA_FindHandleByPid(&g_server.store, pid, &handle);
if (index == INVALID_INDEX) {
//返回的下标无效,则没找到该对象,需要创建它
//初始化地址
SvcIdentity identity = {(uint32)INVALID_INDEX, (uint32)INVALID_INDEX, (uint32)INVALID_INDEX};
//GetCallingTid()用于获取origin的taskID,即获取发送者的任务ID,这个值是由内核填充的
//根据taskID生成发送者的serviceHandle,赋值给identity的handle
(void)GenServiceHandle(&identity, GetCallingTid(origin));
#ifdef __LINUX__
BinderAcquire(g_server.samgr->context, identity.handle);//该函数在当前版本中暂未实现
#endif
//重新构建handle对象
//发送者的进程ID
handle.pid = pid;
//返回origin的userID,即发送者的用户ID
handle.uid = GetCallingUid(origin);
//发送者的服务handle
handle.handle = identity.handle;
handle.deadId = INVALID_INDEX;
//将指定的PidHandle对象保存在satore中
(void)SASTORA_SaveHandleByPid(&server->store, handle);
//解除死亡的回调函数
(void)UnregisterDeathCallback(identity, handle.deadId);
//再次注册死亡的回调函数
(void)RegisterDeathCallback(server->samgr->context, identity, OnEndpointExit, (void*)((uintptr_t)pid),
&handle.deadId);
}
MUTEX_Unlock(server->mtx);
//将handle.handle的值当作响应消息发送给请求者
IpcIoPushUint32(reply, handle.handle);
HILOG_INFO(HILOG_MODULE_SAMGR, "Register Endpoint<%d, %d, %d>", handle.pid, handle.handle, handle.deadId);
return EC_SUCCESS;
}
处理资源类型为feature的消息
//feature处理函数,根据option类型调用不同的处理函数
static int ProcFeature(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply)
{
//option必须是OP_PUT或者OP_GET
if (option != OP_PUT && option != OP_GET) {
//操作不符合,发送响应,值为EC_INVALID
IpcIoPushInt32(reply, EC_INVALID);
return EC_INVALID;
}
if (g_server.ipcAuth == NULL) {
//获取服务名为 PERMISSION_SERVICE 且功能名为 IPCAUTH 的API接口
g_server.ipcAuth = GetIpcAuthInterface();
}
if (g_server.ipcAuth == NULL) {
//获取接口失败,则响应EC_NOINIT
IpcIoPushInt32(reply, EC_NOINIT);
return EC_NOINIT;
}
int ret = EC_SUCCESS;
//定义一个无效的通信地址
SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
if (option == OP_PUT) {
//操作类型为PUT,调用PUT处理函数,向SamgrServer注册feature
ret = ProcPutFeature(server, origin, req, reply, &identity);
}
if (ret != EC_SUCCESS) {
return ret;
}
if (option == OP_GET) {
//操作类型为GET,调用GET处理函数,向SamgrServer查询指定服务名和功能名的IPC通信地址SvcIdentity
ret = ProcGetFeature(server, origin, req, reply, &identity);
//将结果响应给请求者
IpcIoPushInt32(reply, ret);
if (ret == EC_SUCCESS) {
//若操作成功,将identity响应给请求者
IpcIoPushSvc(reply, &identity);
}
}
return ret;
}
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: