虚拟内存管理 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-memory-virtual.html 更多...
函数 | |
LOS_DL_LIST_HEAD (g_vmSpaceList) | |
初始化全局虚拟空间节点,所有虚拟空间都挂到此节点上. 更多... | |
LosVmSpace * | LOS_CurrSpaceGet (VOID) |
获取当前进程空间结构体指针 更多... | |
LosVmSpace * | LOS_SpaceGet (VADDR_T vaddr) |
获取虚拟地址对应的进程空间结构体指针 更多... | |
LosVmSpace * | LOS_GetKVmSpace (VOID) |
内核空间只有g_kVmSpace一个,所有的内核进程都共用一个内核空间 更多... | |
LOS_DL_LIST * | LOS_GetVmSpaceList (VOID) |
获取进程空间链表指针 g_vmSpaceList中挂的是进程空间 g_kVmSpace, g_vMallocSpace,所有用户进程的空间(独有一个进程空间) 更多... | |
LosVmSpace * | LOS_GetVmallocSpace (VOID) |
获取内核堆空间的全局变量 更多... | |
ULONG_T | OsRegionRbFreeFn (LosRbNode *pstNode) |
释放挂在红黑树上节点,等于释放了线性区 更多... | |
VOID * | OsRegionRbGetKeyFn (LosRbNode *pstNode) |
通过红黑树节点找到对应的线性区 更多... | |
ULONG_T | OsRegionRbCmpKeyFn (const VOID *pNodeKeyA, const VOID *pNodeKeyB) |
比较两个红黑树节点 更多... | |
STATIC BOOL | OsVmSpaceInitCommon (LosVmSpace *vmSpace, VADDR_T *virtTtb) |
OsVmSpaceInitCommon 初始化进程虚拟空间,必须提供L1表的虚拟内存地址 更多... | |
VOID | OsVmMapInit (VOID) |
@note_thinking 这个函数名称和内容不太搭 更多... | |
BOOL | OsKernVmSpaceInit (LosVmSpace *vmSpace, VADDR_T *virtTtb) |
初始化内核虚拟空间 更多... | |
BOOL | OsVMallocSpaceInit (LosVmSpace *vmSpace, VADDR_T *virtTtb) |
初始化内核堆空间 更多... | |
VOID | OsKSpaceInit (VOID) |
内核虚拟空间初始化 更多... | |
BOOL | OsUserVmSpaceInit (LosVmSpace *vmSpace, VADDR_T *virtTtb) |
OsUserVmSpaceInit 用户空间的TTB表是动态申请得来,每个进程有属于自己的L1,L2表 初始化用户进程虚拟空间,主要划分数据区,堆区,映射区和创建mmu 更多... | |
LosVmSpace * | OsCreateUserVmSpace (VOID) |
创建用户进程空间 更多... | |
STATIC BOOL | OsVmSpaceParamCheck (LosVmSpace *vmSpace) |
STATUS_T | LOS_VmSpaceClone (LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace) |
LosVmMapRegion * | OsFindRegion (LosRbTree *regionRbTree, VADDR_T vaddr, size_t len) |
通过虚拟(线性)地址查找所属线性区,红黑树 更多... | |
LosVmMapRegion * | LOS_RegionFind (LosVmSpace *vmSpace, VADDR_T addr) |
查找线性区 根据起始地址在进程空间内查找是否存在 更多... | |
LosVmMapRegion * | LOS_RegionRangeFind (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) |
分配指定开始地址和长度的线性区 更多... | |
BOOL | LOS_IsRegionFileValid (LosVmMapRegion *region) |
映射类型为文件的线性区是否有效 更多... | |
BOOL | OsInsertRegion (LosRbTree *regionRbTree, LosVmMapRegion *region) |
向红黑树中插入线性区 更多... | |
LosVmMapRegion * | OsCreateRegion (VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset) |
创建一个线性区 更多... | |
PADDR_T | LOS_PaddrQuery (VOID *vaddr) |
通过虚拟地址查询映射的物理地址 更多... | |
LosVmMapRegion * | LOS_RegionAlloc (LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff) |
STATIC VOID | OsAnonPagesRemove (LosArchMmu *archMmu, VADDR_T vaddr, UINT32 count) |
STATIC VOID | OsDevPagesRemove (LosArchMmu *archMmu, VADDR_T vaddr, UINT32 count) |
STATIC VOID | OsFilePagesRemove (LosVmSpace *space, LosVmMapRegion *region) |
STATUS_T | LOS_RegionFree (LosVmSpace *space, LosVmMapRegion *region) |
释放进程空间指定线性区 更多... | |
变量 | |
LosMux | g_vmSpaceListMux |
用于锁g_vmSpaceList的互斥量 更多... | |
LosVmSpace | g_kVmSpace |
内核非分配空间,用于内核运行栈,代码区,数据区 更多... | |
LosVmSpace | g_vMallocSpace |
内核分配空间,用于内核分配内存 更多... | |
虚拟内存管理 http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-memory-virtual.html
基本概念 虚拟内存管理是计算机系统管理内存的一种技术。每个进程都有连续的虚拟地址空间,虚拟地址空间的大小由CPU的位数决定, 32位的硬件平台可以提供的最大的寻址空间为0-4GiB。整个4GiB空间分成两部分,LiteOS-A内核占据3GiB的高地址空间, 1GiB的低地址空间留给进程使用。各个进程空间的虚拟地址空间是独立的,代码、数据互不影响。 系统将虚拟内存分割为称为虚拟页的内存块,大小一般为4KiB或64KiB,LiteOS-A内核默认的页的大小是4KiB, 根据需要可以对MMU(Memory Management Units)进行配置。虚拟内存管理操作的最小单位就是一个页, LiteOS-A内核中一个虚拟地址区间region包含地址连续的多个虚拟页,也可只有一个页。同样,物理内存也会按照页大小进行分割, 分割后的每个内存块称为页帧。虚拟地址空间划分:内核态占高地址3GiB(0x40000000 ~ 0xFFFFFFFF), 用户态占低地址1GiB(0x01000000 ~ 0x3F000000),具体见下表,详细可以查看或配置los_vm_zone.h。 内核态地址规划: Zone名称 描述 属性 ---------------------------------------------------------------------------- DMA zone 供IO设备的DMA使用。 Uncache Normal zone 加载内核代码段、数据段、堆和栈的地址区间。 Cache high mem zone可以分配连续的虚拟内存,但其所映射的物理内存不一定连续。Cache 用户态地址规划: Zone名称 描述 属性 ---------------------------------------------------------------------------- 代码段 用户态代码段地址区间。 Cache 堆 用户态堆地址区间。 Cache 栈 用户态栈地址区间。 Cache 共享库 用于加载用户态共享库的地址区间,包括mmap所映射的区间。 Cache 运行机制 虚拟内存管理中,虚拟地址空间是连续的,但是其映射的物理内存并不一定是连续的,如下图所示。 可执行程序加载运行,CPU访问虚拟地址空间的代码或数据时存在两种情况: 1. CPU访问的虚拟地址所在的页,如V0,已经与具体的物理页P0做映射,CPU通过找到进程对应的页表条目(详见虚实映射), 根据页表条目中的物理地址信息访问物理内存中的内容并返回。 2. CPU访问的虚拟地址所在的页,如V2,没有与具体的物理页做映射,系统会触发缺页异常,系统申请一个物理页, 并把相应的信息拷贝到物理页中,并且把物理页的起始地址更新到页表条目中。此时CPU重新执行访问虚拟内存的指令 便能够访问到具体的代码或数据。
在文件 los_vm_map.c 中定义.
LosVmSpace * LOS_CurrSpaceGet | ( | VOID | ) |
获取当前进程空间结构体指针
在文件 los_vm_map.c 第 112 行定义.
LOS_DL_LIST_HEAD | ( | g_vmSpaceList | ) |
初始化全局虚拟空间节点,所有虚拟空间都挂到此节点上.
LosVmSpace * LOS_GetKVmSpace | ( | VOID | ) |
LosVmSpace * LOS_GetVmallocSpace | ( | VOID | ) |
LOS_DL_LIST * LOS_GetVmSpaceList | ( | VOID | ) |
获取进程空间链表指针 g_vmSpaceList中挂的是进程空间 g_kVmSpace, g_vMallocSpace,所有用户进程的空间(独有一个进程空间)
在文件 los_vm_map.c 第 135 行定义.
BOOL LOS_IsRegionFileValid | ( | LosVmMapRegion * | region | ) |
映射类型为文件的线性区是否有效
在文件 los_vm_map.c 第 512 行定义.
PADDR_T LOS_PaddrQuery | ( | VOID * | vaddr | ) |
通过虚拟地址查询映射的物理地址
在文件 los_vm_map.c 第 550 行定义.
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.c 第 581 行定义.
LosVmMapRegion * LOS_RegionFind | ( | LosVmSpace * | vmSpace, |
VADDR_T | addr | ||
) |
查找线性区 根据起始地址在进程空间内查找是否存在
在文件 los_vm_map.c 第 414 行定义.
STATUS_T LOS_RegionFree | ( | LosVmSpace * | space, |
LosVmMapRegion * | region | ||
) |
释放进程空间指定线性区
复制线性区
劈开线性区
对线性区进行调整
删除线性区
根据指定参数范围[addr,addr+len] 释放用户空间中堆区所占用的物理内存
线性区是否支持扩展
解除一定范围的虚拟地址的映射关系
释放所有线性区
释放虚拟空间
释放虚拟空间,注意内核空间不能被释放掉,永驻内存
虚拟地址和size是否在空间
在进程空间中预留一块内存空间
实现从虚拟地址到物理地址的映射,将指定长度的物理地址区间与虚拟地址区间做映射,需提前申请物理地址区间
对外接口|释放内核堆空间内存
内核空间内存分配,申请小于16KiB的内存则通过堆内存池获取,否则申请多个连续物理页
申请具有对齐属性的内存,申请规则:申请小于16KiB的内存则通过堆内存池获取,否则申请多个连续物理页
重新分配内核内存空间
在文件 los_vm_map.c 第 694 行定义.
LosVmMapRegion * LOS_RegionRangeFind | ( | LosVmSpace * | vmSpace, |
VADDR_T | addr, | ||
size_t | len | ||
) |
LosVmSpace * LOS_SpaceGet | ( | VADDR_T | vaddr | ) |
获取虚拟地址对应的进程空间结构体指针
在文件 los_vm_map.c 第 117 行定义.
STATUS_T LOS_VmSpaceClone | ( | LosVmSpace * | oldVmSpace, |
LosVmSpace * | newVmSpace | ||
) |
在文件 los_vm_map.c 第 318 行定义.
VADDR_T OsAllocRange | ( | LosVmSpace * | vmSpace, |
size_t | len | ||
) |
分配指定长度的线性区
在文件 los_vm_map.c 第 436 行定义.
VADDR_T OsAllocSpecificRange | ( | LosVmSpace * | vmSpace, |
VADDR_T | vaddr, | ||
size_t | len, | ||
UINT32 | regionFlags | ||
) |
分配指定开始地址和长度的线性区
在文件 los_vm_map.c 第 485 行定义.
STATIC VOID OsAnonPagesRemove | ( | LosArchMmu * | archMmu, |
VADDR_T | vaddr, | ||
UINT32 | count | ||
) |
删除匿名页,匿名页就是内存映射页 1.解除映射关系 2.释放物理内存
在文件 los_vm_map.c 第 625 行定义.
LosVmMapRegion * OsCreateRegion | ( | VADDR_T | vaddr, |
size_t | len, | ||
UINT32 | regionFlags, | ||
unsigned long | offset | ||
) |
创建一个线性区
在文件 los_vm_map.c 第 531 行定义.
LosVmSpace * OsCreateUserVmSpace | ( | VOID | ) |
创建用户进程空间
在文件 los_vm_map.c 第 281 行定义.
STATIC VOID OsDevPagesRemove | ( | LosArchMmu * | archMmu, |
VADDR_T | vaddr, | ||
UINT32 | count | ||
) |
STATIC VOID OsFilePagesRemove | ( | LosVmSpace * | space, |
LosVmMapRegion * | region | ||
) |
LosVmMapRegion * OsFindRegion | ( | LosRbTree * | regionRbTree, |
VADDR_T | vaddr, | ||
size_t | len | ||
) |
通过虚拟(线性)地址查找所属线性区,红黑树
在文件 los_vm_map.c 第 400 行定义.
BOOL OsInsertRegion | ( | LosRbTree * | regionRbTree, |
LosVmMapRegion * | region | ||
) |
向红黑树中插入线性区
在文件 los_vm_map.c 第 521 行定义.
BOOL OsKernVmSpaceInit | ( | LosVmSpace * | vmSpace, |
VADDR_T * | virtTtb | ||
) |
初始化内核虚拟空间
在文件 los_vm_map.c 第 224 行定义.
VOID OsKSpaceInit | ( | VOID | ) |
内核虚拟空间初始化
在文件 los_vm_map.c 第 250 行定义.
ULONG_T OsRegionRbCmpKeyFn | ( | const VOID * | pNodeKeyA, |
const VOID * | pNodeKeyB | ||
) |
VOID * OsRegionRbGetKeyFn | ( | LosRbNode * | pstNode | ) |
BOOL OsUserVmSpaceInit | ( | LosVmSpace * | vmSpace, |
VADDR_T * | virtTtb | ||
) |
OsUserVmSpaceInit 用户空间的TTB表是动态申请得来,每个进程有属于自己的L1,L2表 初始化用户进程虚拟空间,主要划分数据区,堆区,映射区和创建mmu
virtTtb | |
vmSpace |
在文件 los_vm_map.c 第 265 行定义.
BOOL OsVMallocSpaceInit | ( | LosVmSpace * | vmSpace, |
VADDR_T * | virtTtb | ||
) |
VOID OsVmMapInit | ( | VOID | ) |
@note_thinking 这个函数名称和内容不太搭
在文件 los_vm_map.c 第 216 行定义.
STATIC BOOL OsVmSpaceInitCommon | ( | LosVmSpace * | vmSpace, |
VADDR_T * | virtTtb | ||
) |
OsVmSpaceInitCommon 初始化进程虚拟空间,必须提供L1表的虚拟内存地址
virtTtb | L1表的地址,TTB表地址 |
vmSpace |
在文件 los_vm_map.c 第 199 行定义.
STATIC BOOL OsVmSpaceParamCheck | ( | LosVmSpace * | vmSpace | ) |
LosVmSpace g_kVmSpace |
内核非分配空间,用于内核运行栈,代码区,数据区
在文件 los_vm_map.c 第 105 行定义.
LosVmSpace g_vMallocSpace |
内核分配空间,用于内核分配内存
在文件 los_vm_map.c 第 106 行定义.
LosMux g_vmSpaceListMux |
用于锁g_vmSpaceList的互斥量
在文件 los_vm_map.c 第 103 行定义.