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🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请看下图提示:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值