OpenHarmony轻量系统服务管理|系统功能的存储机制详解(二)

100 篇文章 0 订阅
100 篇文章 2 订阅

往期知识点记录:

函数实现详解

上一篇文章分析了Sastore存储机制中的数据结构以及根据名称查找指定服务和指定功能的函数。本文继续对本部分的其他函数进行分析。相关函数实现的代码位于distributedschedule_samgr_lite\samgr_endpoint\source\sa_store.c

存储pidhandle信息
/*
    函数功能:将指定的PidHandle对象保存在satore中
    函数参数:@saStore:系统功能的存储结构
             @handle:待存储的PidHandle对象
    函数返回:保存成功 返回EC_SUCCESS,保存失败 返回EC_NOMEMORY
    函数描述:首先根据PidHandle中的pid去查找saStore的maps中是否存在相同pid
             若存在则根据PidHandle中的handle决定是否更新
             若不存在,则创建新的PidHandle结点,并按照从小打大的顺序将新建的PidHandle结点插入到指定位置
*/
int SASTORA_SaveHandleByPid(SAStore *saStore, PidHandle handle)
{
    //初始化
    PidHandle saved = {.handle = INVALID_INDEX};
    //根据pid获取对应的PidHandle对象的下标,查询到的对象保存在saved中
    int index = SASTORA_FindHandleByPid(saStore, handle.pid, &saved);
    if (saved.handle == handle.handle) {
        //handle在saStore中已存在,则返回EC_SUCCESS
        return EC_SUCCESS;
    }
    //sastore中有与指定的pid匹配的对象,但是它们的handle值不同
    if (index != INVALID_INDEX) {
        //返回的下标有效,即找到了相应的对象,直接更新handle
        saStore->maps[index] = handle;
        return EC_SUCCESS;
    }
    //返回的下标无效,不存在相应的对象,需要新建结点进行保存
    if (saStore->mapSize <= saStore->mapTop) {
        //若maps所指向的内存无空闲空间,则需要重新申请一块更大的内存,以GROW_STEP为增长步长
        PidHandle *newMap = (PidHandle *)SAMGR_Malloc(sizeof(PidHandle) * (saStore->mapSize + GROW_STEP));
        if (newMap == NULL) {
            //内存不足
            return EC_NOMEMORY;
        }
        if (saStore->maps != NULL) {
            //maps有指向内存空间,需要将旧内存中的数据拷贝到新的内存中
            (void)memcpy_s(newMap, sizeof(PidHandle) * (saStore->mapSize + GROW_STEP),
                           saStore->maps, sizeof(PidHandle) * saStore->mapSize);
        }
        //暂存旧的map指向,需要释放内存
        PidHandle *oldMap = saStore->maps;
        //指向新的内存空间
        saStore->maps = newMap;
        //更新内存空间大小
        saStore->mapSize += GROW_STEP;
        SAMGR_Free(oldMap);
    }
    //从最后一个结点进行判断,依次往前比较
    int i;
    for (i = saStore->mapTop - 1; i >= 0; --i) {
        if (saStore->maps[i].pid < handle.pid) {
            break;
        }
        //当前结点大于待存储的结点,当前结点向后移动
        saStore->maps[i + 1] = saStore->maps[i];
    }
    //找到合适的下标并保存
    saStore->maps[i + 1] = handle;
    //更新元素个数maptop的值
    ++(saStore->mapTop);
    return EC_SUCCESS;
}
根据pid查找pidhandle对象
/*
    函数功能:在sastore的maps中查找与callingPid相同的PidHandle对象
    函数参数:@saStore:系统功能的信息存储结构体
             @callingPid:进程ID号
             @handle:进程信息
    函数返回:匹配成功 返回对象下标,匹配失败 返回INVALID_INDEX
    函数描述:在saStore的maps中,使用二分查找的方式,查找与指定的callingPid匹配的PidHandle对象。
             该对象由handle返回,对应的下标由函数返回。
*/
int SASTORA_FindHandleByPid(SAStore *saStore, pid_t callingPid, PidHandle *handle)
{
    //参数检查
    if (saStore == NULL || saStore->maps == NULL || handle == NULL) {
        return INVALID_INDEX;
    }
    //获取最高位元素在数组中的下标
    int16 high = saStore->mapTop - 1;
    //设置最低位元素在数组中的下标为0
    int16 low = 0;
    //在saStore->maps中存储的PidHandle对象是按照pid的值从小到大排列的
    //采用二分查找的方式,提高查询速度
    while (low <= high) {
        //二分查找
        int16 mid = (high + low) / 2;//取中间元素的下标
        if (saStore->maps[mid].pid == callingPid) {
            //若找到与指定callingPid相同的PidHandle,则赋值给handle,并返回对应的下标
            *handle = saStore->maps[mid];
            return mid;
        }
        if (saStore->maps[mid].pid < callingPid) {
            //若待查询的callingPid的值大于中间元素的pid值,则更新最低位元素的下标,继续在中间值的右半段匹配
            low = mid + 1;
            continue;
        }
        //待查询的callingPid的值小于中间元素的pid值,则更新最高位元素的下标,继续在中间值的左半段匹配
        high = mid - 1;
    }
    //若未找到,则返回INVALID_INDEX
    return INVALID_INDEX;
}
根据handle查找pidhandle对象
//根据指定的handle,查找saStore中对应的PidHandle
//查找成功返回相应的PidHandle,失败返回一个INVALID_INDEX的PidHandle
PidHandle SASTORA_FindPidHandleByIpcHandle(const SAStore *saStore, uint32 handle)
{
    //初始化
    PidHandle pidHandle = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
    //参数检查
    if (saStore == NULL || saStore->maps == NULL) {
        return pidHandle;
    }
    int i;
    //遍历maps,匹配对应的handle
    for (i = 0; i < saStore->mapTop; i++) {
        if (saStore->maps[i].handle == handle) {
            return saStore->maps[i];
        }
    }
    return pidHandle;
}
清除与指定pid相关的信息
/*
    函数功能:清除与pid相关的注册信息
    函数描述:首先获取sastore的maps中与pid相同的PidHandle对象。
             然后根据pidHandle.handle的值删除和释放sastore中指定服务和功能的信息。
             最后判断该pidHandle对象是否是maps数组中的最后一个元素。
             若是最后一个元素则直接更新maps的元素大小,若不是 则需要将该pidHandle对象之后的元素全部往前移动。这是数组删除一个元素的缺点
*/
int SASTORA_ClearByPid(SAStore *saStore, pid_t pid)
{
    PidHandle pidHandle;
    //在sastore的maps中查找与callingPid相同的PidHandle对象,由pidHandle返回,并返回其对应的下标
    int index = SASTORA_FindHandleByPid(saStore, pid, &pidHandle);
    if (index == INVALID_INDEX) {
        //没找到该对象,清除操作无效,返回EC_INVALID
        return EC_INVALID;
    }
    //根据handle的值删除指定的ListNode结点及serviceInfo下属的所有FeatureNode,并释放占用的内存资源
    SASTORA_ClearServiceByHandle(saStore, pidHandle.handle);
    if (saStore->mapTop <= (index + 1)) {
        //找到的pidHandle对象是数组中最后一个元素,则更新mapTop并返回EC_SUCCESS
        saStore->mapTop--;
        return EC_SUCCESS;
    }//找到的pidHandle对象不是数组中最后一个元素,需要移动元素
    //将index后的元素向前移动
    errno_t err = memmove_s(&saStore->maps[index], sizeof(PidHandle) * (saStore->mapTop - index),
                            &saStore->maps[index + 1], sizeof(PidHandle) * (saStore->mapTop - index - 1));
    if (err != EOK) {
        return EC_FAILURE;
    }
    saStore->mapTop--;
    return EC_SUCCESS;
}

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请看下图提示:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值