更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_vm_map.h 文件参考

浏览源代码.

结构体

struct  file
 
struct  page_mapping
 
struct  VmMapRange
 
struct  VmFault
 缺页结构信息体 更多...
 
struct  VmFileOps
 虚拟内存文件操作函数指针,上层开发可理解为 class 里的方法,注意是对线性区的操作 , 文件操作 见于g_commVmOps 更多...
 
struct  VmMapRegion
 
struct  VmSpace
 虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间 更多...
 

类型定义

typedef struct VmMapRange LosVmMapRange
 
typedef struct VmMapRegion LosVmMapRegion
 
typedef struct VmFileOps LosVmFileOps
 
typedef struct VmSpace LosVmSpace
 虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间 更多...
 
typedef struct VmFault LosVmPgFault
 缺页结构信息体 更多...
 

函数

STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags (unsigned long prot, unsigned long flags)
 从外部权限标签转化为线性区权限标签 更多...
 
STATIC INLINE BOOL LOS_IsKernelAddress (VADDR_T vaddr)
 虚拟地址是否在内核空间 更多...
 
STATIC INLINE BOOL LOS_IsKernelAddressRange (VADDR_T vaddr, size_t len)
 给定地址范围是否都在内核空间中 更多...
 
STATIC INLINE VADDR_T LOS_RegionEndAddr (LosVmMapRegion *region)
 获取线性区的结束地址 更多...
 
STATIC INLINE size_t LOS_RegionSize (VADDR_T start, VADDR_T end)
 获取线性区大小 更多...
 
STATIC INLINE BOOL LOS_IsRegionTypeFile (LosVmMapRegion *region)
 是否为文件映射区 更多...
 
STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly (LosVmMapRegion *region)
 permanent 用户进程永久/常驻区 更多...
 
STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly (LosVmMapRegion *region)
 是否为私有线性区 更多...
 
STATIC INLINE VOID LOS_SetRegionTypeFile (LosVmMapRegion *region)
 设置线性区为文件映射 更多...
 
STATIC INLINE BOOL LOS_IsRegionTypeDev (LosVmMapRegion *region)
 是否为设备映射线性区 /dev/... 更多...
 
STATIC INLINE VOID LOS_SetRegionTypeDev (LosVmMapRegion *region)
 设为设备映射线性区 更多...
 
STATIC INLINE BOOL LOS_IsRegionTypeAnon (LosVmMapRegion *region)
 是否为匿名swap映射线性区 更多...
 
STATIC INLINE VOID LOS_SetRegionTypeAnon (LosVmMapRegion *region)
 设为匿名swap映射线性区 更多...
 
STATIC INLINE BOOL LOS_IsUserAddress (VADDR_T vaddr)
 虚拟地址是否在用户空间 更多...
 
STATIC INLINE BOOL LOS_IsUserAddressRange (VADDR_T vaddr, size_t len)
 虚拟地址[vaddr,vaddr + len]是否在用户空间 更多...
 
STATIC INLINE BOOL LOS_IsVmallocAddress (VADDR_T vaddr)
 
STATIC INLINE BOOL OsIsVmRegionEmpty (LosVmSpace *vmSpace)
 是否为一个空线性区 更多...
 
LosVmSpaceLOS_GetKVmSpace (VOID)
 内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间 更多...
 
LOS_DL_LISTLOS_GetVmSpaceList (VOID)
 获取进程空间链表指针 g_vmSpaceList中挂的是进程空间 g_kVmSpace, g_vMallocSpace,所有用户进程的空间(独有一个进程空间) 更多...
 
LosVmSpaceLOS_GetVmallocSpace (VOID)
 获取内核堆空间的全局变量 更多...
 
VOID OsInitMappingStartUp (VOID)
 OsInitMappingStartUp 开始初始化mmu 更多...
 
VOID OsKSpaceInit (VOID)
 内核虚拟空间初始化 更多...
 
BOOL LOS_IsRangeInSpace (const LosVmSpace *space, VADDR_T vaddr, size_t size)
 
STATUS_T LOS_VmSpaceReserve (LosVmSpace *space, size_t size, VADDR_T vaddr)
 
INT32 OsUserHeapFree (LosVmSpace *vmSpace, VADDR_T addr, size_t len)
 
VADDR_T OsAllocRange (LosVmSpace *vmSpace, size_t len)
 分配指定长度的线性区 更多...
 
VADDR_T OsAllocSpecificRange (LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags)
 分配指定开始地址和长度的线性区 更多...
 
LosVmMapRegionOsCreateRegion (VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset)
 创建一个线性区 更多...
 
BOOL OsInsertRegion (LosRbTree *regionRbTree, LosVmMapRegion *region)
 向红黑树中插入线性区 更多...
 
LosVmSpaceLOS_SpaceGet (VADDR_T vaddr)
 获取虚拟地址对应的进程空间结构体指针 更多...
 
LosVmSpaceLOS_CurrSpaceGet (VOID)
 获取当前进程空间结构体指针 更多...
 
BOOL LOS_IsRegionFileValid (LosVmMapRegion *region)
 映射类型为文件的线性区是否有效 更多...
 
LosVmMapRegionLOS_RegionRangeFind (LosVmSpace *vmSpace, VADDR_T addr, size_t len)
 查找线性区 根据地址区间在进程空间内查找是否存在 更多...
 
LosVmMapRegionLOS_RegionFind (LosVmSpace *vmSpace, VADDR_T addr)
 查找线性区 根据起始地址在进程空间内查找是否存在 更多...
 
PADDR_T LOS_PaddrQuery (VOID *vaddr)
 通过虚拟地址查询映射的物理地址 更多...
 
LosVmMapRegionLOS_RegionAlloc (LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff)
 
STATUS_T OsRegionsRemove (LosVmSpace *space, VADDR_T vaddr, size_t size)
 
STATUS_T OsVmRegionAdjust (LosVmSpace *space, VADDR_T vaddr, size_t size)
 
LosVmMapRegionOsVmRegionDup (LosVmSpace *space, LosVmMapRegion *oldRegion, VADDR_T vaddr, size_t size)
 
STATUS_T OsIsRegionCanExpand (LosVmSpace *space, LosVmMapRegion *region, size_t size)
 
STATUS_T LOS_RegionFree (LosVmSpace *space, LosVmMapRegion *region)
 释放进程空间指定线性区 更多...
 
STATUS_T LOS_VmSpaceFree (LosVmSpace *space)
 
STATUS_T LOS_VaddrToPaddrMmap (LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, size_t len, UINT32 flags)
 
BOOL OsUserVmSpaceInit (LosVmSpace *vmSpace, VADDR_T *virtTtb)
 OsUserVmSpaceInit 用户空间的TTB表是动态申请得来,每个进程有属于自己的L1,L2表 初始化用户进程虚拟空间,主要划分数据区,堆区,映射区和创建mmu 更多...
 
LosVmSpaceOsCreateUserVmSpace (VOID)
 创建用户进程空间 更多...
 
STATUS_T LOS_VmSpaceClone (LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace)
 
LosMuxOsGVmSpaceMuxGet (VOID)
 
STATUS_T OsUnMMap (LosVmSpace *space, VADDR_T addr, size_t size)
 
STATUS_T OsVmSpaceRegionFree (LosVmSpace *space)
 
VOID * LOS_VMalloc (size_t size)
 
VOID LOS_VFree (const VOID *addr)
 
VOID * LOS_KernelMalloc (UINT32 size)
 
VOID * LOS_KernelMallocAlign (UINT32 size, UINT32 boundary)
 
VOID * LOS_KernelRealloc (VOID *ptr, UINT32 size)
 
VOID LOS_KernelFree (VOID *ptr)
 

类型定义说明

◆ LosVmFileOps

typedef struct VmFileOps LosVmFileOps

在文件 los_vm_map.h91 行定义.

◆ LosVmMapRange

typedef struct VmMapRange LosVmMapRange

◆ LosVmMapRegion

typedef struct VmMapRegion LosVmMapRegion

在文件 los_vm_map.h89 行定义.

◆ LosVmPgFault

typedef struct VmFault LosVmPgFault

缺页结构信息体

◆ LosVmSpace

typedef struct VmSpace LosVmSpace

虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间

在文件 los_vm_map.h93 行定义.

函数说明

◆ LOS_CurrSpaceGet()

LosVmSpace * LOS_CurrSpaceGet ( VOID  )

获取当前进程空间结构体指针

在文件 los_vm_map.c112 行定义.

113{
114 return OsCurrProcessGet()->vmSpace;
115}
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
LosVmSpace * vmSpace
函数调用图:
这是这个函数的调用关系图:

◆ LOS_GetKVmSpace()

LosVmSpace * LOS_GetKVmSpace ( VOID  )

内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间

在文件 los_vm_map.c130 行定义.

131{
132 return &g_kVmSpace;
133}
LosVmSpace g_kVmSpace
内核非分配空间,用于内核运行栈,代码区,数据区
Definition: los_vm_map.c:105
这是这个函数的调用关系图:

◆ LOS_GetVmallocSpace()

LosVmSpace * LOS_GetVmallocSpace ( VOID  )

获取内核堆空间的全局变量

在文件 los_vm_map.c140 行定义.

141{
142 return &g_vMallocSpace;
143}
LosVmSpace g_vMallocSpace
内核分配空间,用于内核分配内存
Definition: los_vm_map.c:106
这是这个函数的调用关系图:

◆ LOS_GetVmSpaceList()

LOS_DL_LIST * LOS_GetVmSpaceList ( VOID  )

获取进程空间链表指针 g_vmSpaceList中挂的是进程空间 g_kVmSpace, g_vMallocSpace,所有用户进程的空间(独有一个进程空间)

在文件 los_vm_map.c135 行定义.

136{
137 return &g_vmSpaceList;
138}
这是这个函数的调用关系图:

◆ LOS_IsKernelAddress()

STATIC INLINE BOOL LOS_IsKernelAddress ( VADDR_T  vaddr)

虚拟地址是否在内核空间

在文件 los_vm_map.h213 行定义.

214{
215 return ((vaddr >= (VADDR_T)KERNEL_ASPACE_BASE) &&
216 (vaddr <= ((VADDR_T)KERNEL_ASPACE_BASE + ((VADDR_T)KERNEL_ASPACE_SIZE - 1))));
217}
unsigned long VADDR_T
Definition: los_typedef.h:208
这是这个函数的调用关系图:

◆ LOS_IsKernelAddressRange()

STATIC INLINE BOOL LOS_IsKernelAddressRange ( VADDR_T  vaddr,
size_t  len 
)

给定地址范围是否都在内核空间中

在文件 los_vm_map.h219 行定义.

220{
221 return (vaddr + len > vaddr) && LOS_IsKernelAddress(vaddr) && (LOS_IsKernelAddress(vaddr + len - 1));
222}
STATIC INLINE BOOL LOS_IsKernelAddress(VADDR_T vaddr)
虚拟地址是否在内核空间
Definition: los_vm_map.h:213
函数调用图:

◆ LOS_IsRangeInSpace()

BOOL LOS_IsRangeInSpace ( const LosVmSpace space,
VADDR_T  vaddr,
size_t  size 
)
这是这个函数的调用关系图:

◆ LOS_IsRegionFileValid()

BOOL LOS_IsRegionFileValid ( LosVmMapRegion region)

映射类型为文件的线性区是否有效

在文件 los_vm_map.c512 行定义.

513{
514 if ((region != NULL) && (LOS_IsRegionTypeFile(region)) &&
515 (region->unTypeData.rf.vnode != NULL)) {
516 return TRUE;
517 }
518 return FALSE;
519}
STATIC INLINE BOOL LOS_IsRegionTypeFile(LosVmMapRegion *region)
是否为文件映射区
Definition: los_vm_map.h:234
struct VmMapRegion::@4::VmRegionFile rf
union VmMapRegion::@4 unTypeData
函数调用图:
这是这个函数的调用关系图:

◆ LOS_IsRegionFlagPrivateOnly()

STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly ( LosVmMapRegion region)

是否为私有线性区

在文件 los_vm_map.h245 行定义.

246{
247 return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE);
248}
UINT32 regionFlags
Definition: los_vm_map.h:125
这是这个函数的调用关系图:

◆ LOS_IsRegionPermUserReadOnly()

STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly ( LosVmMapRegion region)

permanent 用户进程永久/常驻区

在文件 los_vm_map.h239 行定义.

240{
241 return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) ==
242 (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ));
243}
这是这个函数的调用关系图:

◆ LOS_IsRegionTypeAnon()

STATIC INLINE BOOL LOS_IsRegionTypeAnon ( LosVmMapRegion region)

是否为匿名swap映射线性区

在文件 los_vm_map.h265 行定义.

266{
267 return region->regionType == VM_MAP_REGION_TYPE_ANON;
268}
UINT8 regionType
Definition: los_vm_map.h:128

◆ LOS_IsRegionTypeDev()

STATIC INLINE BOOL LOS_IsRegionTypeDev ( LosVmMapRegion region)

是否为设备映射线性区 /dev/...

在文件 los_vm_map.h255 行定义.

256{
257 return region->regionType == VM_MAP_REGION_TYPE_DEV;
258}
这是这个函数的调用关系图:

◆ LOS_IsRegionTypeFile()

STATIC INLINE BOOL LOS_IsRegionTypeFile ( LosVmMapRegion region)

是否为文件映射区

在文件 los_vm_map.h234 行定义.

235{
236 return region->regionType == VM_MAP_REGION_TYPE_FILE;
237}
这是这个函数的调用关系图:

◆ LOS_IsUserAddress()

STATIC INLINE BOOL LOS_IsUserAddress ( VADDR_T  vaddr)

虚拟地址是否在用户空间

在文件 los_vm_map.h275 行定义.

276{
277 return ((vaddr >= USER_ASPACE_BASE) &&
278 (vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1))));
279}
这是这个函数的调用关系图:

◆ LOS_IsUserAddressRange()

STATIC INLINE BOOL LOS_IsUserAddressRange ( VADDR_T  vaddr,
size_t  len 
)

虚拟地址[vaddr,vaddr + len]是否在用户空间

在文件 los_vm_map.h281 行定义.

282{
283 return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1));
284}
STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
虚拟地址是否在用户空间
Definition: los_vm_map.h:275
函数调用图:
这是这个函数的调用关系图:

◆ LOS_IsVmallocAddress()

STATIC INLINE BOOL LOS_IsVmallocAddress ( VADDR_T  vaddr)

在文件 los_vm_map.h287 行定义.

288{
289 return ((vaddr >= VMALLOC_START) &&
290 (vaddr <= (VMALLOC_START + (VMALLOC_SIZE - 1))));
291}
这是这个函数的调用关系图:

◆ LOS_KernelFree()

VOID LOS_KernelFree ( VOID *  ptr)
这是这个函数的调用关系图:

◆ LOS_KernelMalloc()

VOID * LOS_KernelMalloc ( UINT32  size)

thread safety these is used to malloc or free kernel memory. when the size is large and close to multiples of pages, will alloc pmm pages, otherwise alloc bestfit memory.

这是这个函数的调用关系图:

◆ LOS_KernelMallocAlign()

VOID * LOS_KernelMallocAlign ( UINT32  size,
UINT32  boundary 
)
这是这个函数的调用关系图:

◆ LOS_KernelRealloc()

VOID * LOS_KernelRealloc ( VOID *  ptr,
UINT32  size 
)
这是这个函数的调用关系图:

◆ LOS_PaddrQuery()

PADDR_T LOS_PaddrQuery ( VOID *  vaddr)

通过虚拟地址查询映射的物理地址

在文件 los_vm_map.c550 行定义.

551{
552 PADDR_T paddr = 0;
553 STATUS_T status;
554 LosVmSpace *space = NULL;
555 LosArchMmu *archMmu = NULL;
556 //先取出对应空间的mmu
557 if (LOS_IsKernelAddress((VADDR_T)(UINTPTR)vaddr)) {//是否内核空间地址
558 archMmu = &g_kVmSpace.archMmu;
559 } else if (LOS_IsUserAddress((VADDR_T)(UINTPTR)vaddr)) {//是否为用户空间地址
560 space = OsCurrProcessGet()->vmSpace;
561 archMmu = &space->archMmu;
562 } else if (LOS_IsVmallocAddress((VADDR_T)(UINTPTR)vaddr)) {//是否为分配空间地址,堆区地址
563 archMmu = &g_vMallocSpace.archMmu;
564 } else {
565 VM_ERR("vaddr is beyond range");
566 return 0;
567 }
568
569 status = LOS_ArchMmuQuery(archMmu, (VADDR_T)(UINTPTR)vaddr, &paddr, 0);//查询物理地址
570 if (status == LOS_OK) {
571 return paddr;
572 } else {
573 return 0;
574 }
575}
STATUS_T LOS_ArchMmuQuery(const LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T *paddr, UINT32 *flags)
LOS_ArchMmuQuery 获取进程空间虚拟地址对应的物理地址以及映射属性。 本函数是内核高频函数,通过MMU查询虚拟地址是否映射过,带走映射的物理地址和权限
Definition: los_arch_mmu.c:569
unsigned long PADDR_T
Definition: los_typedef.h:207
int STATUS_T
Definition: los_typedef.h:215
unsigned long UINTPTR
Definition: los_typedef.h:68
STATIC INLINE BOOL LOS_IsVmallocAddress(VADDR_T vaddr)
Definition: los_vm_map.h:287
内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。
Definition: los_arch_mmu.h:86
虚拟空间,每个进程都有一个属于自己的虚拟内存地址空间
Definition: los_vm_map.h:146
LosArchMmu archMmu
Definition: los_vm_map.h:157
函数调用图:
这是这个函数的调用关系图:

◆ LOS_RegionAlloc()

LosVmMapRegion * LOS_RegionAlloc ( LosVmSpace vmSpace,
VADDR_T  vaddr,
size_t  len,
UINT32  regionFlags,
VM_OFFSET_T  pgoff 
)

这里不是真的分配物理内存,而是逻辑上画一个连续的区域,标记这个区域可以拿用,表示内存已经归你了。 但真正的物理内存的占用会延迟到使用的时候才由缺页中断调入内存

If addr is NULL, then the kernel chooses the address at which to create the mapping; this is the most portable method of creating a new mapping. If addr is not NULL, then the kernel takes it as where to place the mapping;

在文件 los_vm_map.c581 行定义.

582{
583 VADDR_T rstVaddr;
584 LosVmMapRegion *newRegion = NULL;
585 BOOL isInsertSucceed = FALSE;
586 /**
587 * If addr is NULL, then the kernel chooses the address at which to create the mapping;
588 * this is the most portable method of creating a new mapping. If addr is not NULL,
589 * then the kernel takes it as where to place the mapping;
590 */
591 (VOID)LOS_MuxAcquire(&vmSpace->regionMux);//获得互斥锁
592 if (vaddr == 0) {//如果地址是0,根据线性区管理的实际情况,自动创建虚拟地址, 这是创建新映射的最便捷的方法。
593 rstVaddr = OsAllocRange(vmSpace, len);
594 } else {
595 /* if it is already mmapped here, we unmmap it | 如果已经被映射了, 则解除映射关系*/
596 rstVaddr = OsAllocSpecificRange(vmSpace, vaddr, len, regionFlags);//创建包含指定虚拟地址的线性区, rstVaddr != vaddr || rstVaddr == vaddr
597 if (rstVaddr == 0) {
598 VM_ERR("alloc specific range va: %#x, len: %#x failed", vaddr, len);
599 goto OUT;
600 }
601 }
602 if (rstVaddr == 0) {//没有可供映射的虚拟地址
603 goto OUT;
604 }
605
606 newRegion = OsCreateRegion(rstVaddr, len, regionFlags, pgoff);//创建一个线性区,指定线性区的开始地址rstVaddr ...
607 if (newRegion == NULL) {
608 goto OUT;
609 }
610 newRegion->space = vmSpace;
611 isInsertSucceed = OsInsertRegion(&vmSpace->regionRbTree, newRegion);//插入红黑树和双循环链表中管理
612 if (isInsertSucceed == FALSE) {//插入失败
613 (VOID)LOS_MemFree(m_aucSysMem0, newRegion);//从内存池中释放
614 newRegion = NULL;
615 }
616
617OUT:
618 (VOID)LOS_MuxRelease(&vmSpace->regionMux);//释放互斥锁
619 return newRegion;
620}
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
size_t BOOL
Definition: los_typedef.h:88
STATIC INLINE STATUS_T LOS_MuxAcquire(LosMux *m)
Definition: los_vm_lock.h:48
STATIC INLINE STATUS_T LOS_MuxRelease(LosMux *m)
Definition: los_vm_lock.h:53
LosVmMapRegion * OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset)
创建一个线性区
Definition: los_vm_map.c:531
VADDR_T OsAllocRange(LosVmSpace *vmSpace, size_t len)
分配指定长度的线性区
Definition: los_vm_map.c:436
VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags)
分配指定开始地址和长度的线性区
Definition: los_vm_map.c:485
BOOL OsInsertRegion(LosRbTree *regionRbTree, LosVmMapRegion *region)
向红黑树中插入线性区
Definition: los_vm_map.c:521
LosVmSpace * space
所属虚拟空间,虚拟空间由多个线性区组成
Definition: los_vm_map.h:121
LosRbTree regionRbTree
Definition: los_vm_map.h:148
LosMux regionMux
Definition: los_vm_map.h:149
函数调用图:
这是这个函数的调用关系图:

◆ LOS_RegionEndAddr()

STATIC INLINE VADDR_T LOS_RegionEndAddr ( LosVmMapRegion region)

获取线性区的结束地址

在文件 los_vm_map.h224 行定义.

225{
226 return (region->range.base + region->range.size - 1);
227}
UINT32 size
Definition: los_vm_map.h:85
VADDR_T base
Definition: los_vm_map.h:84
LosVmMapRange range
Definition: los_vm_map.h:123
这是这个函数的调用关系图:

◆ LOS_RegionFind()

LosVmMapRegion * LOS_RegionFind ( LosVmSpace vmSpace,
VADDR_T  addr 
)

查找线性区 根据起始地址在进程空间内查找是否存在

在文件 los_vm_map.c414 行定义.

415{
416 LosVmMapRegion *region = NULL;
417
418 (VOID)LOS_MuxAcquire(&vmSpace->regionMux);//因进程空间是隔离的,所以此处只会涉及到任务(线程)之间的竞争,故使用互斥锁,而自旋锁则用于CPU核间的竞争
419 region = OsFindRegion(&vmSpace->regionRbTree, addr, 1);
420 (VOID)LOS_MuxRelease(&vmSpace->regionMux);
421
422 return region;
423}
LosVmMapRegion * OsFindRegion(LosRbTree *regionRbTree, VADDR_T vaddr, size_t len)
通过虚拟(线性)地址查找所属线性区,红黑树
Definition: los_vm_map.c:400
函数调用图:
这是这个函数的调用关系图:

◆ LOS_RegionFree()

STATUS_T LOS_RegionFree ( LosVmSpace space,
LosVmMapRegion region 
)

释放进程空间指定线性区

复制线性区

劈开线性区

对线性区进行调整

删除线性区

根据指定参数范围[addr,addr+len] 释放用户空间中堆区所占用的物理内存

线性区是否支持扩展

解除一定范围的虚拟地址的映射关系

释放所有线性区

释放虚拟空间

释放虚拟空间,注意内核空间不能被释放掉,永驻内存

虚拟地址和size是否在空间

在进程空间中预留一块内存空间

实现从虚拟地址到物理地址的映射,将指定长度的物理地址区间与虚拟地址区间做映射,需提前申请物理地址区间

对外接口|释放内核堆空间内存

内核空间内存分配,申请小于16KiB的内存则通过堆内存池获取,否则申请多个连续物理页

申请具有对齐属性的内存,申请规则:申请小于16KiB的内存则通过堆内存池获取,否则申请多个连续物理页

重新分配内核内存空间

在文件 los_vm_map.c694 行定义.

这是这个函数的调用关系图:

◆ LOS_RegionRangeFind()

LosVmMapRegion * LOS_RegionRangeFind ( LosVmSpace vmSpace,
VADDR_T  addr,
size_t  len 
)

查找线性区 根据地址区间在进程空间内查找是否存在

在文件 los_vm_map.c425 行定义.

426{
427 LosVmMapRegion *region = NULL;
428
429 (VOID)LOS_MuxAcquire(&vmSpace->regionMux);
430 region = OsFindRegion(&vmSpace->regionRbTree, addr, len);
431 (VOID)LOS_MuxRelease(&vmSpace->regionMux);
432
433 return region;
434}
函数调用图:
这是这个函数的调用关系图:

◆ LOS_RegionSize()

STATIC INLINE size_t LOS_RegionSize ( VADDR_T  start,
VADDR_T  end 
)

获取线性区大小

在文件 los_vm_map.h229 行定义.

230{
231 return (end - start + 1);
232}
这是这个函数的调用关系图:

◆ LOS_SetRegionTypeAnon()

STATIC INLINE VOID LOS_SetRegionTypeAnon ( LosVmMapRegion region)

设为匿名swap映射线性区

在文件 los_vm_map.h270 行定义.

271{
272 region->regionType = VM_MAP_REGION_TYPE_ANON;
273}
这是这个函数的调用关系图:

◆ LOS_SetRegionTypeDev()

STATIC INLINE VOID LOS_SetRegionTypeDev ( LosVmMapRegion region)

设为设备映射线性区

在文件 los_vm_map.h260 行定义.

261{
262 region->regionType = VM_MAP_REGION_TYPE_DEV;
263}
这是这个函数的调用关系图:

◆ LOS_SetRegionTypeFile()

STATIC INLINE VOID LOS_SetRegionTypeFile ( LosVmMapRegion region)

设置线性区为文件映射

在文件 los_vm_map.h250 行定义.

251{
252 region->regionType = VM_MAP_REGION_TYPE_FILE;
253}
这是这个函数的调用关系图:

◆ LOS_SpaceGet()

LosVmSpace * LOS_SpaceGet ( VADDR_T  vaddr)

获取虚拟地址对应的进程空间结构体指针

在文件 los_vm_map.c117 行定义.

118{
119 if (LOS_IsKernelAddress(vaddr)) { //是否为内核空间
120 return LOS_GetKVmSpace(); //获取内核空间
121 } else if (LOS_IsUserAddress(vaddr)) {//是否为用户空间
122 return LOS_CurrSpaceGet();
123 } else if (LOS_IsVmallocAddress(vaddr)) {//是否为内核分配空间
124 return LOS_GetVmallocSpace();//获取内核分配空间
125 } else {
126 return NULL;
127 }
128}
LosVmSpace * LOS_CurrSpaceGet(VOID)
获取当前进程空间结构体指针
Definition: los_vm_map.c:112
LosVmSpace * LOS_GetVmallocSpace(VOID)
获取内核堆空间的全局变量
Definition: los_vm_map.c:140
LosVmSpace * LOS_GetKVmSpace(VOID)
内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间
Definition: los_vm_map.c:130
函数调用图:
这是这个函数的调用关系图:

◆ LOS_VaddrToPaddrMmap()

STATUS_T LOS_VaddrToPaddrMmap ( LosVmSpace space,
VADDR_T  vaddr,
PADDR_T  paddr,
size_t  len,
UINT32  flags 
)
这是这个函数的调用关系图:

◆ LOS_VFree()

VOID LOS_VFree ( const VOID *  addr)
这是这个函数的调用关系图:

◆ LOS_VMalloc()

VOID * LOS_VMalloc ( size_t  size)

thread safety it is used to malloc continuous virtual memory, no sure for continuous physical memory.

这是这个函数的调用关系图:

◆ LOS_VmSpaceClone()

STATUS_T LOS_VmSpaceClone ( LosVmSpace oldVmSpace,
LosVmSpace newVmSpace 
)

在文件 los_vm_map.c318 行定义.

319{
320 LosVmMapRegion *oldRegion = NULL;
321 LosVmMapRegion *newRegion = NULL;
322 LosRbNode *pstRbNode = NULL;
323 LosRbNode *pstRbNodeNext = NULL;
324 STATUS_T ret = LOS_OK;
325 UINT32 numPages;
326 PADDR_T paddr;
327 VADDR_T vaddr;
328 UINT32 intSave;
329 LosVmPage *page = NULL;
330 UINT32 flags;
331 UINT32 i;
332
333 if ((OsVmSpaceParamCheck(oldVmSpace) == FALSE) || (OsVmSpaceParamCheck(newVmSpace) == FALSE)) {
334 return LOS_ERRNO_VM_INVALID_ARGS;
335 }
336
337 if ((OsIsVmRegionEmpty(oldVmSpace) == TRUE) || (oldVmSpace == &g_kVmSpace)) {//不允许clone内核空间,内核空间是独一无二的.
338 return LOS_ERRNO_VM_INVALID_ARGS;
339 }
340 //空间克隆的主体实现是:线性区重新一个个分配物理内存,重新映射.
341 /* search the region list */
342 newVmSpace->mapBase = oldVmSpace->mapBase; //复制映射区基址
343 newVmSpace->heapBase = oldVmSpace->heapBase; //复制堆区基址
344 newVmSpace->heapNow = oldVmSpace->heapNow; //复制堆区当前使用到哪了
345 (VOID)LOS_MuxAcquire(&oldVmSpace->regionMux);
346 RB_SCAN_SAFE(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)//红黑树循环开始
347 oldRegion = (LosVmMapRegion *)pstRbNode;
348 newRegion = OsVmRegionDup(newVmSpace, oldRegion, oldRegion->range.base, oldRegion->range.size);//复制线性区
349 if (newRegion == NULL) {
350 VM_ERR("dup new region failed");
351 ret = LOS_ERRNO_VM_NO_MEMORY;
352 break;
353 }
354
355#ifdef LOSCFG_KERNEL_SHM
356 if (oldRegion->regionFlags & VM_MAP_REGION_FLAG_SHM) {//如果老线性区是共享内存
357 OsShmFork(newVmSpace, oldRegion, newRegion);//fork共享线性区,如此新虚拟空间也能用那个线性区
358 continue;//不往下走了,因为共享内存不需要重新映射,下面无非就是需要MMU映射虚拟地址<-->物理地址
359 }
360#endif
361
362 if (oldRegion == oldVmSpace->heap) {//如果这个线性区是堆区
363 newVmSpace->heap = newRegion;//那么新的线性区也是新虚拟空间的堆区
364 }
365
366 numPages = newRegion->range.size >> PAGE_SHIFT;//计算线性区页数
367 for (i = 0; i < numPages; i++) {//一页一页进行重新映射
368 vaddr = newRegion->range.base + (i << PAGE_SHIFT);
369 if (LOS_ArchMmuQuery(&oldVmSpace->archMmu, vaddr, &paddr, &flags) != LOS_OK) {//先查物理地址
370 continue;
371 }
372
373 page = LOS_VmPageGet(paddr);//通过物理页获取物理内存的页框
374 if (page != NULL) {
375 LOS_AtomicInc(&page->refCounts);//refCounts 自增
376 }
377 if (flags & VM_MAP_REGION_FLAG_PERM_WRITE) {//可写入区标签
378 LOS_ArchMmuUnmap(&oldVmSpace->archMmu, vaddr, 1);//先删除老空间映射
379 LOS_ArchMmuMap(&oldVmSpace->archMmu, vaddr, paddr, 1, flags & ~VM_MAP_REGION_FLAG_PERM_WRITE);//老空间重新映射
380 }
381 LOS_ArchMmuMap(&newVmSpace->archMmu, vaddr, paddr, 1, flags & ~VM_MAP_REGION_FLAG_PERM_WRITE);//映射新空间
382
383#ifdef LOSCFG_FS_VFS //文件系统开关
384 if (LOS_IsRegionFileValid(oldRegion)) {//是都是一个文件映射线性区
385 LosFilePage *fpage = NULL;
386 LOS_SpinLockSave(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, &intSave);
387 fpage = OsFindGetEntry(&oldRegion->unTypeData.rf.vnode->mapping, newRegion->pgOff + i);
388 if ((fpage != NULL) && (fpage->vmPage == page)) { /* cow page no need map */
389 OsAddMapInfo(fpage, &newVmSpace->archMmu, vaddr);//添加文件页映射,记录页面被进程映射过
390 }
391 LOS_SpinUnlockRestore(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, intSave);
392 }
393#endif
394 }
395 RB_SCAN_SAFE_END(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)//红黑树循环结束
396 (VOID)LOS_MuxRelease(&oldVmSpace->regionMux);
397 return ret;
398}
STATIC INLINE VOID LOS_AtomicInc(Atomic *v)
Atomic addSelf.
Definition: los_atomic.h:253
STATUS_T LOS_ArchMmuMap(LosArchMmu *archMmu, VADDR_T vaddr, PADDR_T paddr, size_t count, UINT32 flags)
LOS_ArchMmuMap 映射进程空间虚拟地址区间与物理地址区间 所谓的map就是生成L1,L2页表项的过程
Definition: los_arch_mmu.c:891
STATUS_T LOS_ArchMmuUnmap(LosArchMmu *archMmu, VADDR_T vaddr, size_t count)
LOS_ArchMmuUnmap 解除进程空间虚拟地址区间与物理地址区间的映射关系
Definition: los_arch_mmu.c:619
VOID LOS_SpinUnlockRestore(SPIN_LOCK_S *lock, UINT32 intSave)
Definition: los_spinlock.c:108
VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
Definition: los_spinlock.c:98
unsigned int UINT32
Definition: los_typedef.h:57
VOID OsAddMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
LosFilePage * OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff)
STATIC BOOL OsVmSpaceParamCheck(LosVmSpace *vmSpace)
Definition: los_vm_map.c:309
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
映射类型为文件的线性区是否有效
Definition: los_vm_map.c:512
STATIC INLINE BOOL OsIsVmRegionEmpty(LosVmSpace *vmSpace)
是否为一个空线性区
Definition: los_vm_map.h:293
LosVmMapRegion * OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADDR_T vaddr, size_t size)
LosVmPage * LOS_VmPageGet(PADDR_T paddr)
通过物理地址获取页框
Definition: los_vm_page.c:120
VOID OsShmFork(LosVmSpace *space, LosVmMapRegion *oldRegion, LosVmMapRegion *newRegion)
fork 一个共享线性区
Definition: shm.c:393
文件页结构体
struct VmPage * vmPage
物理页框
VM_OFFSET_T pgOff
Definition: los_vm_map.h:124
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
Definition: los_vm_page.h:53
Atomic refCounts
Definition: los_vm_page.h:57
LosVmMapRegion * heap
Definition: los_vm_map.h:154
VADDR_T mapBase
Definition: los_vm_map.h:155
VADDR_T heapBase
Definition: los_vm_map.h:152
VADDR_T heapNow
Definition: los_vm_map.h:153
函数调用图:
这是这个函数的调用关系图:

◆ LOS_VmSpaceFree()

STATUS_T LOS_VmSpaceFree ( LosVmSpace space)
这是这个函数的调用关系图:

◆ LOS_VmSpaceReserve()

STATUS_T LOS_VmSpaceReserve ( LosVmSpace space,
size_t  size,
VADDR_T  vaddr 
)
这是这个函数的调用关系图:

◆ OsAllocRange()

VADDR_T OsAllocRange ( LosVmSpace vmSpace,
size_t  len 
)

分配指定长度的线性区

在文件 los_vm_map.c436 行定义.

437{
438 LosVmMapRegion *curRegion = NULL;
439 LosRbNode *pstRbNode = NULL;
440 LosRbNode *pstRbNodeTmp = NULL;
441 LosRbTree *regionRbTree = &vmSpace->regionRbTree;
442 VADDR_T curEnd = vmSpace->mapBase;//获取映射区基地址
443 VADDR_T nextStart;
444
445 curRegion = LOS_RegionFind(vmSpace, vmSpace->mapBase);
446 if (curRegion != NULL) {
447 pstRbNode = &curRegion->rbNode;
448 curEnd = curRegion->range.base + curRegion->range.size;
449 RB_MID_SCAN(regionRbTree, pstRbNode)
450 curRegion = (LosVmMapRegion *)pstRbNode;
451 nextStart = curRegion->range.base;
452 if (nextStart < curEnd) {
453 continue;
454 }
455 if ((nextStart - curEnd) >= len) {
456 return curEnd;
457 } else {
458 curEnd = curRegion->range.base + curRegion->range.size;
459 }
460 RB_MID_SCAN_END(regionRbTree, pstRbNode)
461 } else {//红黑树扫描排序,从小到大
462 /* rbtree scan is sorted, from small to big */
463 RB_SCAN_SAFE(regionRbTree, pstRbNode, pstRbNodeTmp)
464 curRegion = (LosVmMapRegion *)pstRbNode;
465 nextStart = curRegion->range.base;
466 if (nextStart < curEnd) {
467 continue;
468 }
469 if ((nextStart - curEnd) >= len) {
470 return curEnd;
471 } else {
472 curEnd = curRegion->range.base + curRegion->range.size;
473 }
474 RB_SCAN_SAFE_END(regionRbTree, pstRbNode, pstRbNodeTmp)
475 }
476
477 nextStart = vmSpace->mapBase + vmSpace->mapSize;
478 if ((nextStart >= curEnd) && ((nextStart - curEnd) >= len)) {
479 return curEnd;
480 }
481
482 return 0;
483}
LosVmMapRegion * LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr)
查找线性区 根据起始地址在进程空间内查找是否存在
Definition: los_vm_map.c:414
LosRbNode rbNode
Definition: los_vm_map.h:120
UINT32 mapSize
Definition: los_vm_map.h:156
函数调用图:
这是这个函数的调用关系图:

◆ OsAllocSpecificRange()

VADDR_T OsAllocSpecificRange ( LosVmSpace vmSpace,
VADDR_T  vaddr,
size_t  len,
UINT32  regionFlags 
)

分配指定开始地址和长度的线性区

在文件 los_vm_map.c485 行定义.

486{
487 STATUS_T status;
488
489 if (LOS_IsRangeInSpace(vmSpace, vaddr, len) == FALSE) {//虚拟地址是否在进程空间范围内
490 return 0;
491 }
492
493 if ((LOS_RegionFind(vmSpace, vaddr) != NULL) ||
494 (LOS_RegionFind(vmSpace, vaddr + len - 1) != NULL) ||
495 (LOS_RegionRangeFind(vmSpace, vaddr, len - 1) != NULL)) {//没找到的情况
496 if ((regionFlags & VM_MAP_REGION_FLAG_FIXED_NOREPLACE) != 0) {
497 return 0;
498 } else if ((regionFlags & VM_MAP_REGION_FLAG_FIXED) != 0) {//线性区未填满,则解除这部分空间的映射
499 status = LOS_UnMMap(vaddr, len);//解除映射
500 if (status != LOS_OK) {
501 VM_ERR("unmap specific range va: %#x, len: %#x failed, status: %d", vaddr, len, status);
502 return 0;
503 }
504 } else {
505 return OsAllocRange(vmSpace, len);//默认分配一个
506 }
507 }
508
509 return vaddr;
510}
LosVmMapRegion * LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len)
查找线性区 根据地址区间在进程空间内查找是否存在
Definition: los_vm_map.c:425
BOOL LOS_IsRangeInSpace(const LosVmSpace *space, VADDR_T vaddr, size_t size)
STATUS_T LOS_UnMMap(VADDR_T addr, size_t size)
解除映射关系
函数调用图:
这是这个函数的调用关系图:

◆ OsCreateRegion()

LosVmMapRegion * OsCreateRegion ( VADDR_T  vaddr,
size_t  len,
UINT32  regionFlags,
unsigned long  offset 
)

创建一个线性区

在文件 los_vm_map.c531 行定义.

532{
533 LosVmMapRegion *region = LOS_MemAlloc(m_aucSysMem0, sizeof(LosVmMapRegion));//只是分配一个线性区结构体
534 if (region == NULL) {
535 VM_ERR("memory allocate for LosVmMapRegion failed");
536 return region;
537 }
538 //创建线性区的本质就是在画饼,见如下操作:
539 (void)memset_s(region, sizeof(LosVmMapRegion), 0, sizeof(LosVmMapRegion));
540 region->range.base = vaddr; //虚拟地址作为线性区的基地址
541 region->range.size = len; //线性区大小,这是线性区构思最巧妙的地方,只要不过分,蓝图随便画。
542 region->pgOff = offset; //页标
543 region->regionFlags = regionFlags;//标识,可读/可写/可执行
544 region->regionType = VM_MAP_REGION_TYPE_NONE;//未映射
545 region->forkFlags = 0; //
546 region->shmid = -1; //默认线性区为不共享,无共享资源ID
547 return region;
548}
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
struct VmMapRegion LosVmMapRegion
Definition: los_vm_map.h:89
UINT32 shmid
Definition: los_vm_map.h:126
UINT8 forkFlags
Definition: los_vm_map.h:127
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
函数调用图:
这是这个函数的调用关系图:

◆ OsCreateUserVmSpace()

LosVmSpace * OsCreateUserVmSpace ( VOID  )

创建用户进程空间

在文件 los_vm_map.c281 行定义.

282{
283 BOOL retVal = FALSE;
284
285 LosVmSpace *space = LOS_MemAlloc(m_aucSysMem0, sizeof(LosVmSpace));//在内核空间申请用户进程空间
286 if (space == NULL) {
287 return NULL;
288 }
289 //此处为何直接申请物理页帧存放用户进程的页表,大概是因为所有页表都被存放在内核空间(g_kVmSpace)而非内核分配空间(g_vMallocSpace)
290 VADDR_T *ttb = LOS_PhysPagesAllocContiguous(1);//分配一个物理页用于存放虚实映射关系表, 即:L1表
291 if (ttb == NULL) {//若连页表都没有,剩下的也别玩了.
292 (VOID)LOS_MemFree(m_aucSysMem0, space);
293 return NULL;
294 }
295
296 (VOID)memset_s(ttb, PAGE_SIZE, 0, PAGE_SIZE);//4K空间置0
297 retVal = OsUserVmSpaceInit(space, ttb);//初始化用户空间,mmu
298 LosVmPage *vmPage = OsVmVaddrToPage(ttb);//找到所在物理页框
299 if ((retVal == FALSE) || (vmPage == NULL)) {
300 (VOID)LOS_MemFree(m_aucSysMem0, space);
302 return NULL;
303 }
304 LOS_ListAdd(&space->archMmu.ptList, &(vmPage->node));//页表链表,先挂上L1,后续还会挂上 N个L2表
305
306 return space;
307}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
Definition: los_list.h:217
BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
OsUserVmSpaceInit 用户空间的TTB表是动态申请得来,每个进程有属于自己的L1,L2表 初始化用户进程虚拟空间,主要划分数据区,堆区,映射区和创建mmu
Definition: los_vm_map.c:265
VOID * LOS_PhysPagesAllocContiguous(size_t nPages)
分配连续的物理页
Definition: los_vm_phys.c:478
VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages)
释放指定页数地址连续的物理内存
Definition: los_vm_phys.c:494
LosVmPage * OsVmVaddrToPage(VOID *ptr)
通过虚拟地址找映射的物理页框
Definition: los_vm_phys.c:295
LOS_DL_LIST ptList
Definition: los_arch_mmu.h:93
LOS_DL_LIST node
Definition: los_vm_page.h:54
函数调用图:
这是这个函数的调用关系图:

◆ OsCvtProtFlagsToRegionFlags()

STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags ( unsigned long  prot,
unsigned long  flags 
)

从外部权限标签转化为线性区权限标签

在文件 los_vm_map.h197 行定义.

198{
199 UINT32 regionFlags = 0;
200
201 regionFlags |= VM_MAP_REGION_FLAG_PERM_USER; //必须是用户空间区
202 regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0; //映射区可被读
203 regionFlags |= (prot & PROT_WRITE) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0;
204 regionFlags |= (prot & PROT_EXEC) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_EXECUTE) : 0;
205 regionFlags |= (flags & MAP_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0;
206 regionFlags |= (flags & MAP_PRIVATE) ? VM_MAP_REGION_FLAG_PRIVATE : 0;
207 regionFlags |= (flags & MAP_FIXED) ? VM_MAP_REGION_FLAG_FIXED : 0;
208 regionFlags |= (flags & MAP_FIXED_NOREPLACE) ? VM_MAP_REGION_FLAG_FIXED_NOREPLACE : 0;
209
210 return regionFlags;
211}
这是这个函数的调用关系图:

◆ OsGVmSpaceMuxGet()

LosMux * OsGVmSpaceMuxGet ( VOID  )
这是这个函数的调用关系图:

◆ OsInitMappingStartUp()

VOID OsInitMappingStartUp ( VOID  )

OsInitMappingStartUp 开始初始化mmu

返回
参见

在文件 los_arch_mmu.c1263 行定义.

1264{
1265 OsArmInvalidateTlbBarrier();//使TLB失效
1266
1267 OsSwitchTmpTTB();//切换到临时TTB ,请想想为何要切换到临时 @note_thinking
1268
1269 OsSetKSectionAttr(KERNEL_VMM_BASE, FALSE);//设置内核空间属性
1270 OsSetKSectionAttr(UNCACHED_VMM_BASE, TRUE);//设置未缓存空间属性
1272}
STATIC VOID OsSetKSectionAttr(UINTPTR virtAddr, BOOL uncached)
设置内核空间段属性,可看出内核空间是固定映射到物理地址
STATIC VOID OsKSectionNewAttrEnable(VOID)
STATIC VOID OsSwitchTmpTTB(VOID)
切换临时页表
STATIC INLINE VOID OsArmInvalidateTlbBarrier(VOID)
Definition: los_tlb_v6.h:48
函数调用图:
这是这个函数的调用关系图:

◆ OsInsertRegion()

BOOL OsInsertRegion ( LosRbTree regionRbTree,
LosVmMapRegion region 
)

向红黑树中插入线性区

在文件 los_vm_map.c521 行定义.

522{
523 if (LOS_RbAddNode(regionRbTree, (LosRbNode *)region) == FALSE) {
524 VM_ERR("insert region failed, base: %#x, size: %#x", region->range.base, region->range.size);
525 OsDumpAspace(region->space);
526 return FALSE;
527 }
528 return TRUE;
529}
ULONG_T LOS_RbAddNode(LosRbTree *pstTree, LosRbNode *pstNew)
Definition: los_rbtree.c:705
VOID OsDumpAspace(LosVmSpace *space)
dump 指定虚拟空间的信息
Definition: los_vm_dump.c:396
函数调用图:
这是这个函数的调用关系图:

◆ OsIsRegionCanExpand()

STATUS_T OsIsRegionCanExpand ( LosVmSpace space,
LosVmMapRegion region,
size_t  size 
)
这是这个函数的调用关系图:

◆ OsIsVmRegionEmpty()

STATIC INLINE BOOL OsIsVmRegionEmpty ( LosVmSpace vmSpace)

是否为一个空线性区

在文件 los_vm_map.h293 行定义.

294{
295 if (vmSpace->regionRbTree.ulNodes == 0) {
296 return TRUE;
297 }
298 return FALSE;
299}
ULONG_T ulNodes
Definition: los_rbtree.h:66
这是这个函数的调用关系图:

◆ OsKSpaceInit()

VOID OsKSpaceInit ( VOID  )

内核虚拟空间初始化

在文件 los_vm_map.c250 行定义.

251{
252 OsVmMapInit();//初始化后续操作 g_vmSpaceList 的互斥锁
253 OsKernVmSpaceInit(&g_kVmSpace, OsGFirstTableGet()); //初始化内核进程虚拟空间
254 OsVMallocSpaceInit(&g_vMallocSpace, OsGFirstTableGet());//初始化内核动态分配空间
255}
VADDR_T * OsGFirstTableGet(VOID)
Definition: los_arch_mmu.c:186
BOOL OsKernVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
初始化内核虚拟空间
Definition: los_vm_map.c:224
BOOL OsVMallocSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
初始化内核堆空间
Definition: los_vm_map.c:237
VOID OsVmMapInit(VOID)
@note_thinking 这个函数名称和内容不太搭
Definition: los_vm_map.c:216
函数调用图:
这是这个函数的调用关系图:

◆ OsRegionsRemove()

STATUS_T OsRegionsRemove ( LosVmSpace space,
VADDR_T  vaddr,
size_t  size 
)
这是这个函数的调用关系图:

◆ OsUnMMap()

STATUS_T OsUnMMap ( LosVmSpace space,
VADDR_T  addr,
size_t  size 
)
这是这个函数的调用关系图:

◆ OsUserHeapFree()

INT32 OsUserHeapFree ( LosVmSpace vmSpace,
VADDR_T  addr,
size_t  len 
)
这是这个函数的调用关系图:

◆ OsUserVmSpaceInit()

BOOL OsUserVmSpaceInit ( LosVmSpace vmSpace,
VADDR_T virtTtb 
)

OsUserVmSpaceInit 用户空间的TTB表是动态申请得来,每个进程有属于自己的L1,L2表 初始化用户进程虚拟空间,主要划分数据区,堆区,映射区和创建mmu

参数
virtTtb
vmSpace
返回
参见

在文件 los_vm_map.c265 行定义.

266{
267 vmSpace->base = USER_ASPACE_BASE;//用户空间基地址
268 vmSpace->size = USER_ASPACE_SIZE;//用户空间大小
269 vmSpace->mapBase = USER_MAP_BASE;//用户空间映射基地址
270 vmSpace->mapSize = USER_MAP_SIZE;//用户空间映射大小
271 vmSpace->heapBase = USER_HEAP_BASE;//用户堆区开始地址,只有用户进程需要设置这里,动态内存的开始地址
272 vmSpace->heapNow = USER_HEAP_BASE;//堆区最新指向地址,用户堆空间大小可通过系统调用 do_brk()扩展
273 vmSpace->heap = NULL; //最近分配的一个堆线性区
274#ifdef LOSCFG_DRIVERS_TZDRIVER
275 vmSpace->codeStart = 0;
276 vmSpace->codeEnd = 0;
277#endif
278 return OsVmSpaceInitCommon(vmSpace, virtTtb);//创建MMU,为后续的虚实映射做好初始化的工作
279}
STATIC BOOL OsVmSpaceInitCommon(LosVmSpace *vmSpace, VADDR_T *virtTtb)
OsVmSpaceInitCommon 初始化进程虚拟空间,必须提供L1表的虚拟内存地址
Definition: los_vm_map.c:199
VADDR_T base
Definition: los_vm_map.h:150
VADDR_T codeStart
Definition: los_vm_map.h:159
VADDR_T codeEnd
Definition: los_vm_map.h:160
UINT32 size
Definition: los_vm_map.h:151
函数调用图:
这是这个函数的调用关系图:

◆ OsVmRegionAdjust()

STATUS_T OsVmRegionAdjust ( LosVmSpace space,
VADDR_T  vaddr,
size_t  size 
)
这是这个函数的调用关系图:

◆ OsVmRegionDup()

LosVmMapRegion * OsVmRegionDup ( LosVmSpace space,
LosVmMapRegion oldRegion,
VADDR_T  vaddr,
size_t  size 
)
这是这个函数的调用关系图:

◆ OsVmSpaceRegionFree()

STATUS_T OsVmSpaceRegionFree ( LosVmSpace space)
这是这个函数的调用关系图: