函数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; } 函数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 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:
https://qr18.cn/CgxrRy
https://qr18.cn/CgxrRy
https://qr18.cn/CgxrRy
https://qr18.cn/CgxrRy
https://qr18.cn/CgxrRy
https://qr21.cn/FV7h05