鸿蒙轻内核A核源码分析系列五 虚实映射(6)虚拟映射修改转移

csdn推荐

6.1 映射属性修改函数LOS_ArchMmuChangeProt

函数LOS_ArchMmuChangeProt用于修改进程空间虚拟地址区间的映射保护属性,其中参数archMmu为进程空间的MMU结构体,vaddr为虚拟地址,count为映射的页数,flags为映射使用的新标签属性信息。其中函数名称中的Prot是英文Protect的简写。⑴处对参数进行校验,⑵处查询虚拟地址映射的物理地址,如果没有映射,则执行⑶把虚拟地址增加1个内存页大小继续修改下一个内存页的映射保护属性。如果存在映射,则执行⑷处代码。先解除当前内存页的映射,然后执行⑸使用新的映射属性重新映射,⑹处虚拟地址增加1个内存页大小继续修改下一个内存页的属性。

STATUS_T LOS_ArchMmuChangeProt(LosArchMmu *archMmu, VADDR_T vaddr, size_t count, UINT32 flags)
{
    STATUS_T status;
    PADDR_T paddr = 0;
⑴  if ((archMmu == NULL) || (vaddr == 0) || (count == 0)) {
        VM_ERR("invalid args: archMmu %p, vaddr %p, count %d", archMmu, vaddr, count);
        return LOS_NOK;
    }
    while (count > 0) {
        count--;
⑵      status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);
        if (status != LOS_OK) {
⑶          vaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
            continue;
        }
⑷      status = LOS_ArchMmuUnmap(archMmu, vaddr, 1);
        if (status < 0) {
            VM_ERR("invalid args:aspace %p, vaddr %p, count %d", archMmu, vaddr, count);
            return LOS_NOK;
        }
⑸      status = LOS_ArchMmuMap(archMmu, vaddr, paddr, 1, flags);
        if (status < 0) {
            VM_ERR("invalid args:aspace %p, vaddr %p, count %d",
                   archMmu, vaddr, count);
            return LOS_NOK;
        }
⑹      vaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
    }
    return LOS_OK;
}

6.2 映射转移函数LOS_ArchMmuMove

函数LOS_ArchMmuMove用于将进程空间中一个虚拟地址区间的映射关系转移至另一块未使用的虚拟地址区间重新做映射,物理内存还是那一块,但是虚拟内存地址旧换新。其中参数oldVaddr为老的虚拟地址,newVaddr为新的虚拟内存地址,count为内存页数量,flags在重新映射时可以更改映射属性信息。⑴处一个内存一个内存页进行循环,先查询老的虚拟地址映射的物理内存。如果没有映射关系,把新旧虚拟内存都增加一个内存页的大小继续循环。⑵处取消老的虚拟地址的映射,⑶处使用新的虚拟内存重新映射到查询到的物理内存地址。⑷把新旧虚拟内存都增加一个内存页的大小,继续处理下一个内存页。

STATUS_T LOS_ArchMmuMove(LosArchMmu *archMmu, VADDR_T oldVaddr, VADDR_T newVaddr, size_t count, UINT32 flags)
{
    STATUS_T status;
    PADDR_T paddr = 0;
    if ((archMmu == NULL) || (oldVaddr == 0) || (newVaddr == 0) || (count == 0)) {
        VM_ERR("invalid args: archMmu %p, oldVaddr %p, newVddr %p, count %d",
               archMmu, oldVaddr, newVaddr, count);
        return LOS_NOK;
    }
    while (count > 0) {
        count--;
⑴      status = LOS_ArchMmuQuery(archMmu, oldVaddr, &paddr, NULL);
        if (status != LOS_OK) {
            oldVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
            newVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
            continue;
        }
        // we need to clear the mapping here and remain the phy page.
⑵      status = LOS_ArchMmuUnmap(archMmu, oldVaddr, 1);
        if (status < 0) {
            VM_ERR("invalid args: archMmu %p, vaddr %p, count %d",
                   archMmu, oldVaddr, count);
            return LOS_NOK;
        }
⑶      status = LOS_ArchMmuMap(archMmu, newVaddr, paddr, 1, flags);
        if (status < 0) {
            VM_ERR("invalid args:archMmu %p, old_vaddr %p, new_addr %p, count %d",
                   archMmu, oldVaddr, newVaddr, count);
            return LOS_NOK;
        }
⑷      oldVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
        newVaddr += MMU_DESCRIPTOR_L2_SMALL_SIZE;
    }
    return LOS_OK;
}

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:

《OpenHarmony源码解析》: 系统架构分析:

OpenHarmony 设备开发学习手册:

OpenHarmony面试题(内含参考答案):

写在最后

文章来源:https://blog.csdn.net/maniuT/article/details/139636750



微信扫描下方的二维码阅读本文

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容