欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 明星 > 鸿蒙轻内核A核源码分析系列五 虚实映射(7)虚实映射Flag属性

鸿蒙轻内核A核源码分析系列五 虚实映射(7)虚实映射Flag属性

2024/10/24 19:16:09 来源:https://blog.csdn.net/u012165769/article/details/142098380  浏览:    关键词:鸿蒙轻内核A核源码分析系列五 虚实映射(7)虚实映射Flag属性

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 轻内核A核源码分析系列一 数据结构-双向循环链表
  • 轻内核A核源码分析系列二 数据结构-位图操作
  • 轻内核A核源码分析系列三 物理内存(1)
  • 轻内核A核源码分析系列三 物理内存(2)
  • 轻内核A核源码分析系列四(1)虚拟内存进程空间编号
  • 轻内核A核源码分析系列四(2) 虚拟内存
  • 轻内核A核源码分析系列四(3) 虚拟内存
  • 轻内核A核源码分析系列五 虚实映射(1)基础概念
  • 轻内核A核源码分析系列五 虚实映射(2)虚实映射初始化
  • 轻内核A核源码分析系列五 虚实映射(3)虚拟物理内存映射
  • 轻内核A核源码分析系列五 虚实映射(5)虚实映射解除
  • 轻内核A核源码分析系列五 虚实映射(6)虚拟映射修改转移
  • 轻内核A核源码分析系列五 虚实映射(7)虚实映射Flag属性
  • 轻内核A核源码分析系列六 MMU协处理器(1)
  • 轻内核A核源码分析系列六 MMU协处理器(2)
  • 轻内核A核源码分析系列七 进程管理 (1)
  • 轻内核A核源码分析系列七 进程管理 (2)
  • 轻内核A核源码分析系列七 进程管理 (3)
  • 持续更新中……

在学习函数LOS_ArchMmuMap()代码时,我们已经了解了虚拟内存如何映射到物理内存,在映射的时候,可以通过UINT 32 flags参数定一些标签属性信息。本节,我们具体了解下内存标签属性信息。先了解下MMU标签属性,然后看看映射内存区间时的映射虚实信息,最后了解下属性信息转换函数。

7.1 MMU标签属性

在映射的时候,对于内存页可以指定一些内存属性,比如权限、内存类型、缓存策略等等。更多信息参考ARM官网资料《ARM® Cortex™-A Series Version: 4.0 Programmer’s Guide》,我们只快速摘录些关键信息。L1页表项的格式如下图所示,其中Type extension (TEX)Shareable (S)Access Permission (AP, APX)、 Cacheable (C)、 Bufferable (B)位表示内存属性信息。在arch\arm\arm\include\los_mmu_descriptor_v6.h文件中定义了MMU L1页表内存属性相关的宏,如下。

/* TEX CB */
#define MMU_DESCRIPTOR_L1_TEX_SHIFT                             12 /* type extension field shift */
#define MMU_DESCRIPTOR_L1_TEX(x)                                \((x) << MMU_DESCRIPTOR_L1_TEX_SHIFT) /* type extension */
#define MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED                 \(MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_NON_CACHEABLE)
#define MMU_DESCRIPTOR_L1_TYPE_NORMAL_NOCACHE                   \(MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_NON_CACHEABLE)
#define MMU_DESCRIPTOR_L1_TYPE_DEVICE_SHARED                    \(MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_WRITE_BACK_ALLOCATE)
#define MMU_DESCRIPTOR_L1_TYPE_DEVICE_NON_SHARED                \(MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_2) | MMU_DESCRIPTOR_NON_CACHEABLE)
#define MMU_DESCRIPTOR_L1_TYPE_NORMAL_WRITE_BACK_ALLOCATE       \(MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE)
#define MMU_DESCRIPTOR_L1_TEX_TYPE_MASK                         \(MMU_DESCRIPTOR_L1_TEX(MMU_DESCRIPTOR_TEX_MASK) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE)#define MMU_DESCRIPTOR_L1_AP2_SHIFT                             15
#define MMU_DESCRIPTOR_L1_AP2(x)                                ((x) << MMU_DESCRIPTOR_L1_AP2_SHIFT)
#define MMU_DESCRIPTOR_L1_AP2_0                                 (MMU_DESCRIPTOR_L1_AP2(0))
#define MMU_DESCRIPTOR_L1_AP2_1                                 (MMU_DESCRIPTOR_L1_AP2(1))
#define MMU_DESCRIPTOR_L1_AP01_SHIFT                            10
#define MMU_DESCRIPTOR_L1_AP01(x)                               ((x) << MMU_DESCRIPTOR_L1_AP01_SHIFT)
#define MMU_DESCRIPTOR_L1_AP01_0                                (MMU_DESCRIPTOR_L1_AP01(0))
#define MMU_DESCRIPTOR_L1_AP01_1                                (MMU_DESCRIPTOR_L1_AP01(1))
#define MMU_DESCRIPTOR_L1_AP01_3                                (MMU_DESCRIPTOR_L1_AP01(3))
#define MMU_DESCRIPTOR_L1_AP_P_NA_U_NA                          (MMU_DESCRIPTOR_L1_AP2_0 | MMU_DESCRIPTOR_L1_AP01_0)
#define MMU_DESCRIPTOR_L1_AP_P_RW_U_RW                          (MMU_DESCRIPTOR_L1_AP2_0 | MMU_DESCRIPTOR_L1_AP01_3)
#define MMU_DESCRIPTOR_L1_AP_P_RW_U_NA                          (MMU_DESCRIPTOR_L1_AP2_0 | MMU_DESCRIPTOR_L1_AP01_1)
#define MMU_DESCRIPTOR_L1_AP_P_RO_U_RO                          (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_3)
#define MMU_DESCRIPTOR_L1_AP_P_RO_U_NA                          (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_1)
#define MMU_DESCRIPTOR_L1_AP_MASK                               (MMU_DESCRIPTOR_L1_AP2_1 | MMU_DESCRIPTOR_L1_AP01_3)

L2页表项的格式如下图所示。在arch\arm\arm\include\los_mmu_descriptor_v6.h文件中定义了MMU L2页表内存属性相关的宏,如下。

#define MMU_DESCRIPTOR_L2_TEX_SHIFT                             6 /* type extension field shift */
#define MMU_DESCRIPTOR_L2_TEX(x)                                \((x) << MMU_DESCRIPTOR_L2_TEX_SHIFT) /* type extension */
#define MMU_DESCRIPTOR_L2_TYPE_STRONGLY_ORDERED                 \(MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_NON_CACHEABLE)
#define MMU_DESCRIPTOR_L2_TYPE_NORMAL_NOCACHE                   \(MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_NON_CACHEABLE)
#define MMU_DESCRIPTOR_L2_TYPE_DEVICE_SHARED                    \(MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_0) | MMU_DESCRIPTOR_WRITE_BACK_ALLOCATE)
#define MMU_DESCRIPTOR_L2_TYPE_DEVICE_NON_SHARED                \(MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_2) | MMU_DESCRIPTOR_NON_CACHEABLE)
#define MMU_DESCRIPTOR_L2_TYPE_NORMAL_WRITE_BACK_ALLOCATE       \(MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_1) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE)
#define MMU_DESCRIPTOR_L2_TEX_TYPE_MASK                         \(MMU_DESCRIPTOR_L2_TEX(MMU_DESCRIPTOR_TEX_MASK) | MMU_DESCRIPTOR_WRITE_BACK_NO_ALLOCATE)
#define MMU_DESCRIPTOR_L2_AP2_SHIFT                             9
#define MMU_DESCRIPTOR_L2_AP2(x)                                ((x) << MMU_DESCRIPTOR_L2_AP2_SHIFT)
#define MMU_DESCRIPTOR_L2_AP2_0                                 (MMU_DESCRIPTOR_L2_AP2(0))
#define MMU_DESCRIPTOR_L2_AP2_1                                 (MMU_DESCRIPTOR_L2_AP2(1))
#define MMU_DESCRIPTOR_L2_AP01_SHIFT                            4
#define MMU_DESCRIPTOR_L2_AP01(x)                               ((x) << MMU_DESCRIPTOR_L2_AP01_SHIFT)
#define MMU_DESCRIPTOR_L2_AP01_0                                (MMU_DESCRIPTOR_L2_AP01(0))
#define MMU_DESCRIPTOR_L2_AP01_1                                (MMU_DESCRIPTOR_L2_AP01(1))
#define MMU_DESCRIPTOR_L2_AP01_3                                (MMU_DESCRIPTOR_L2_AP01(3))
#define MMU_DESCRIPTOR_L2_AP_P_NA_U_NA                          (MMU_DESCRIPTOR_L2_AP2_0 | MMU_DESCRIPTOR_L2_AP01_0)
#define MMU_DESCRIPTOR_L2_AP_P_RW_U_RW                          (MMU_DESCRIPTOR_L2_AP2_0 | MMU_DESCRIPTOR_L2_AP01_3)
#define MMU_DESCRIPTOR_L2_AP_P_RW_U_NA                          (MMU_DESCRIPTOR_L2_AP2_0 | MMU_DESCRIPTOR_L2_AP01_1)
#define MMU_DESCRIPTOR_L2_AP_P_RO_U_RO                          (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_3)
#define MMU_DESCRIPTOR_L2_AP_P_RO_U_NA                          (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_1)
#define MMU_DESCRIPTOR_L2_AP_MASK                               (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_3)

7.2 映射地址区间标签属性

kernel\base\include\los_vm_map.h文件中定义地址区间映射标签属性信息。标签属性信息主要分为4类,如图所示。前2位用于标记释放缓存设备,2-5位用于标记权限信息,6-8位用于标记共享私有等信息,9-19位用于标记stack、heap、data、text、bss、vsdo、mmap、shm、fixed、fixed_noreplace等属性信息。20-23位暂未使用,高8位被共享内存SHM使用。

/* the high 8 bits(24~31) should reserved, shm will use it */
#define     VM_MAP_REGION_FLAG_CACHED               (0<<0)
#define     VM_MAP_REGION_FLAG_UNCACHED             (1<<0)
#define     VM_MAP_REGION_FLAG_UNCACHED_DEVICE      (2<<0) /* only exists on some arches, otherwise UNCACHED */
#define     VM_MAP_REGION_FLAG_STRONGLY_ORDERED     (3<<0) /* only exists on some arches, otherwise UNCACHED */
#define     VM_MAP_REGION_FLAG_CACHE_MASK           (3<<0)
#define     VM_MAP_REGION_FLAG_PERM_USER            (1<<2)
#define     VM_MAP_REGION_FLAG_PERM_READ            (1<<3)
#define     VM_MAP_REGION_FLAG_PERM_WRITE           (1<<4)
#define     VM_MAP_REGION_FLAG_PERM_EXECUTE         (1<<5)
#define     VM_MAP_REGION_FLAG_PROT_MASK            (0xF<<2)
#define     VM_MAP_REGION_FLAG_NS                   (1<<6) /* NON-SECURE */
#define     VM_MAP_REGION_FLAG_SHARED               (1<<7)
#define     VM_MAP_REGION_FLAG_PRIVATE              (1<<8)
#define     VM_MAP_REGION_FLAG_FLAG_MASK            (3<<7)
#define     VM_MAP_REGION_FLAG_STACK                (1<<9)
#define     VM_MAP_REGION_FLAG_HEAP                 (1<<10)
#define     VM_MAP_REGION_FLAG_DATA                 (1<<11)
#define     VM_MAP_REGION_FLAG_TEXT                 (1<<12)
#define     VM_MAP_REGION_FLAG_BSS                  (1<<13)
#define     VM_MAP_REGION_FLAG_VDSO                 (1<<14)
#define     VM_MAP_REGION_FLAG_MMAP                 (1<<15)
#define     VM_MAP_REGION_FLAG_SHM                  (1<<16)
#define     VM_MAP_REGION_FLAG_FIXED                (1<<17)
#define     VM_MAP_REGION_FLAG_FIXED_NOREPLACE      (1<<18)
#define     VM_MAP_REGION_FLAG_INVALID              (1<<19) /* indicates that flags are not specified */

7.3 标签转换操作

7.3.1 OsCvtProtFlagsToRegionFlags函数

函数OsCvtProtFlagsToRegionFlags()把保护属性转换为虚拟内存区间标签属性,该函数在系统调用、共享内存等模块会使用。参数unsigned long prot中的保护标签属性如PROT_READMAP_SHARED等等,定义在文件third_party/musl/porting/liteos_a/kernel/include/sys/mman.h

STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags)
{UINT32 regionFlags = 0;regionFlags |= VM_MAP_REGION_FLAG_PERM_USER;regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0;regionFlags |= (prot & PROT_WRITE) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0;regionFlags |= (prot & PROT_EXEC) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_EXECUTE) : 0;regionFlags |= (flags & MAP_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0;regionFlags |= (flags & MAP_PRIVATE) ? VM_MAP_REGION_FLAG_PRIVATE : 0;regionFlags |= (flags & MAP_FIXED) ? VM_MAP_REGION_FLAG_FIXED : 0;regionFlags |= (flags & MAP_FIXED_NOREPLACE) ? VM_MAP_REGION_FLAG_FIXED_NOREPLACE : 0;return regionFlags;
}

7.3.2 OsCvtSecFlagsToAttrs函数和OsCvtSecAttsToFlags函数

OsCvtSecFlagsToAttrs函数用于把内存区域映射标签属性转换为L1 Section类型页表项的MMU标签属性。该函数又分为2个函数,分别是⑴处的OsCvtSecCacheFlagsToMMUFlags()函数和⑵处的OsCvtSecAccessFlagsToMMUFlags()函数。OsCvtSecCacheFlagsToMMUFlags()函数主要判断内存映射区域的低2位缓存标签属性的转换。OsCvtSecAccessFlagsToMMUFlags()函数用于映射标签属性的2-4位访问权限部分的转换。代码比较简单不再赘述。

⑶处的函数OsCvtSecAttsToFlags()是上述函数OsCvtSecFlagsToAttrs的逆过程,用于把L1 Section类型页表项的MMU标签属性转换为内存区域映射标签属性。自行阅读代码,不再逐行分析。

⑴  STATIC UINT32 OsCvtSecCacheFlagsToMMUFlags(UINT32 flags){UINT32 mmuFlags = 0;switch (flags & VM_MAP_REGION_FLAG_CACHE_MASK) {case VM_MAP_REGION_FLAG_CACHED:mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_NORMAL_WRITE_BACK_ALLOCATE;#ifdef LOSCFG_KERNEL_SMPmmuFlags |= MMU_DESCRIPTOR_L1_SECTION_SHAREABLE;#endifbreak;case VM_MAP_REGION_FLAG_STRONGLY_ORDERED:mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED;break;case VM_MAP_REGION_FLAG_UNCACHED:mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_NORMAL_NOCACHE;break;case VM_MAP_REGION_FLAG_UNCACHED_DEVICE:mmuFlags |= MMU_DESCRIPTOR_L1_TYPE_DEVICE_SHARED;break;default:return LOS_ERRNO_VM_INVALID_ARGS;}return mmuFlags;}⑵  STATIC UINT32 OsCvtSecAccessFlagsToMMUFlags(UINT32 flags){UINT32 mmuFlags = 0;switch (flags & (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE)) {case 0:mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_NA_U_NA;break;case VM_MAP_REGION_FLAG_PERM_READ:case VM_MAP_REGION_FLAG_PERM_USER:mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RO_U_NA;break;case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ:mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RO_U_RO;break;case VM_MAP_REGION_FLAG_PERM_WRITE:case VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE:mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RW_U_NA;break;case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE:case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE:mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_RW_U_RW;break;default:break;}return mmuFlags;}/* convert user level mmu flags to L1 descriptors flags */STATIC UINT32 OsCvtSecFlagsToAttrs(UINT32 flags){UINT32 mmuFlags;mmuFlags = OsCvtSecCacheFlagsToMMUFlags(flags);if (mmuFlags == LOS_ERRNO_VM_INVALID_ARGS) {return mmuFlags;}mmuFlags |= MMU_DESCRIPTOR_L1_SMALL_DOMAIN_CLIENT;mmuFlags |= OsCvtSecAccessFlagsToMMUFlags(flags);if (!(flags & VM_MAP_REGION_FLAG_PERM_EXECUTE)) {mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_XN;}if (flags & VM_MAP_REGION_FLAG_NS) {mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_NON_SECURE;}if (flags & VM_MAP_REGION_FLAG_PERM_USER) {mmuFlags |= MMU_DESCRIPTOR_L1_SECTION_NON_GLOBAL;}return mmuFlags;}⑶  STATIC VOID OsCvtSecAttsToFlags(PTE_T l1Entry, UINT32 *flags){*flags = 0;if (l1Entry & MMU_DESCRIPTOR_L1_SECTION_NON_SECURE) {*flags |= VM_MAP_REGION_FLAG_NS;}switch (l1Entry & MMU_DESCRIPTOR_L1_TEX_TYPE_MASK) {case MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED:*flags |= VM_MAP_REGION_FLAG_STRONGLY_ORDERED;break;case MMU_DESCRIPTOR_L1_TYPE_NORMAL_NOCACHE:*flags |= VM_MAP_REGION_FLAG_UNCACHED;break;case MMU_DESCRIPTOR_L1_TYPE_DEVICE_SHARED:case MMU_DESCRIPTOR_L1_TYPE_DEVICE_NON_SHARED:*flags |= VM_MAP_REGION_FLAG_UNCACHED_DEVICE;break;default:break;}*flags |= VM_MAP_REGION_FLAG_PERM_READ;switch (l1Entry & MMU_DESCRIPTOR_L1_AP_MASK) {case MMU_DESCRIPTOR_L1_AP_P_RO_U_NA:break;case MMU_DESCRIPTOR_L1_AP_P_RW_U_NA:*flags |= VM_MAP_REGION_FLAG_PERM_WRITE;break;case MMU_DESCRIPTOR_L1_AP_P_RO_U_RO:*flags |= VM_MAP_REGION_FLAG_PERM_USER;break;case MMU_DESCRIPTOR_L1_AP_P_RW_U_RW:*flags |= VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE;break;default:break;}if (!(l1Entry & MMU_DESCRIPTOR_L1_SECTION_XN)) {*flags |= VM_MAP_REGION_FLAG_PERM_EXECUTE;}}

7.3.3 OsCvtPte2FlagsToAttrs函数和OsCvtPte2AttsToFlags函数

和上一小节非常类似,上节是L1 Section类型页表项MMU属性和内存区域标签属性的相互转换,本节的2个函数是L2页表项MMU属性和内存区域标签属性的相互转换。函数OsCvtPte2FlagsToAttrs()把内存区域映射标签属性转换为L2页表项MMU属性,又分为2个函数,分别是⑴处的函数OsCvtPte2CacheFlagsToMMUFlags()和⑵处的OsCvtPte2AccessFlagsToMMUFlags()OsCvtPte2CacheFlagsToMMUFlags()函数主要判断内存映射区域的低2位缓存标签属性的转换。OsCvtPte2AccessFlagsToMMUFlags()函数用于映射标签属性的2-4位访问权限部分的转换。代码比较简单不再赘述。

⑶处的函数OsCvtPte2AttsToFlags()是上述函数OsCvtPte2FlagsToAttrs的逆过程,用于把L2页表项的MMU标签属性转换为内存区域映射标签属性。自行阅读代码,不再逐行分析。

⑴  STATIC UINT32 OsCvtPte2CacheFlagsToMMUFlags(UINT32 flags){UINT32 mmuFlags = 0;switch (flags & VM_MAP_REGION_FLAG_CACHE_MASK) {case VM_MAP_REGION_FLAG_CACHED:#ifdef LOSCFG_KERNEL_SMPmmuFlags |= MMU_DESCRIPTOR_L2_SHAREABLE;#endifmmuFlags |= MMU_DESCRIPTOR_L2_TYPE_NORMAL_WRITE_BACK_ALLOCATE;break;case VM_MAP_REGION_FLAG_STRONGLY_ORDERED:mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_STRONGLY_ORDERED;break;case VM_MAP_REGION_FLAG_UNCACHED:mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_NORMAL_NOCACHE;break;case VM_MAP_REGION_FLAG_UNCACHED_DEVICE:mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_DEVICE_SHARED;break;default:return LOS_ERRNO_VM_INVALID_ARGS;}return mmuFlags;}⑵  STATIC UINT32 OsCvtPte2AccessFlagsToMMUFlags(UINT32 flags){UINT32 mmuFlags = 0;switch (flags & (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE)) {case 0:mmuFlags |= MMU_DESCRIPTOR_L1_AP_P_NA_U_NA;break;case VM_MAP_REGION_FLAG_PERM_READ:case VM_MAP_REGION_FLAG_PERM_USER:mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RO_U_NA;break;case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ:mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RO_U_RO;break;case VM_MAP_REGION_FLAG_PERM_WRITE:case VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE:mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RW_U_NA;break;case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE:case VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE:mmuFlags |= MMU_DESCRIPTOR_L2_AP_P_RW_U_RW;break;default:break;}return mmuFlags;}/* convert user level mmu flags to L2 descriptors flags */STATIC UINT32 OsCvtPte2FlagsToAttrs(UINT32 flags){UINT32 mmuFlags;mmuFlags = OsCvtPte2CacheFlagsToMMUFlags(flags);if (mmuFlags == LOS_ERRNO_VM_INVALID_ARGS) {return mmuFlags;}mmuFlags |= OsCvtPte2AccessFlagsToMMUFlags(flags);if (!(flags & VM_MAP_REGION_FLAG_PERM_EXECUTE)) {mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE_XN;} else {mmuFlags |= MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE;}if (flags & VM_MAP_REGION_FLAG_PERM_USER) {mmuFlags |= MMU_DESCRIPTOR_L2_NON_GLOBAL;}return mmuFlags;}⑶  STATIC VOID OsCvtPte2AttsToFlags(PTE_T l1Entry, PTE_T l2Entry, UINT32 *flags){*flags = 0;/* NS flag is only present on L1 entry */if (l1Entry & MMU_DESCRIPTOR_L1_PAGETABLE_NON_SECURE) {*flags |= VM_MAP_REGION_FLAG_NS;}switch (l2Entry & MMU_DESCRIPTOR_L2_TEX_TYPE_MASK) {case MMU_DESCRIPTOR_L2_TYPE_STRONGLY_ORDERED:*flags |= VM_MAP_REGION_FLAG_STRONGLY_ORDERED;break;case MMU_DESCRIPTOR_L2_TYPE_NORMAL_NOCACHE:*flags |= VM_MAP_REGION_FLAG_UNCACHED;break;case MMU_DESCRIPTOR_L2_TYPE_DEVICE_SHARED:case MMU_DESCRIPTOR_L2_TYPE_DEVICE_NON_SHARED:*flags |= VM_MAP_REGION_FLAG_UNCACHED_DEVICE;break;default:break;}*flags |= VM_MAP_REGION_FLAG_PERM_READ;switch (l2Entry & MMU_DESCRIPTOR_L2_AP_MASK) {case MMU_DESCRIPTOR_L2_AP_P_RO_U_NA:break;case MMU_DESCRIPTOR_L2_AP_P_RW_U_NA:*flags |= VM_MAP_REGION_FLAG_PERM_WRITE;break;case MMU_DESCRIPTOR_L2_AP_P_RO_U_RO:*flags |= VM_MAP_REGION_FLAG_PERM_USER;break;case MMU_DESCRIPTOR_L2_AP_P_RW_U_RW:*flags |= VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_WRITE;break;default:break;}if ((l2Entry & MMU_DESCRIPTOR_L2_TYPE_MASK) != MMU_DESCRIPTOR_L2_TYPE_SMALL_PAGE_XN) {*flags |= VM_MAP_REGION_FLAG_PERM_EXECUTE;}}

小结

本文介绍了MMU虚实映射的基本概念,运行机制,分析了映射初始化、映射查询、映射虚拟内存和物理内存,解除虚实映射,更改映射属性,重新映射等常用接口的代码。

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片
在这里插入图片描述