本文我们来熟悉下OpenHarmony
鸿蒙轻内核提供的虚拟内存(Virtual memory)管理模块。
本文中所涉及的源码,以OpenHarmony LiteOS-A
内核为例,均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 获取。如果涉及开发板,则默认以hispark_taurus
为例。
我们首先了解了虚拟内存管理的结构体、相关宏定义,接着会分析内核虚拟地址空间和用户进程虚拟地址空间如何初始化,然后分析虚拟内存区间常用操作包含查找、申请和释放等,最后分析动态内存堆的申请、释放接口的源代码,并简单介绍下内存区间预留接口源代码。
1、 虚拟内存管理相关的结构体
在文件kernel/base/include/los_vm_map.h
中定义了进程地址空间结构体LosVmSpace
,进程地址区间结构体LosVmMapRegion
和进程地址区间范围结构体LosVmMapRange
。每个用户态进程会创建自己的进程空间,内核态会创建2个进程空间,分别g_kVmSpace
和g_vMallocSpace
。从进程空间申请的虚拟内存块使用进程区间LosVmMapRegion
来表示。每个进程空间维护一个红黑树来链接各个进程区间。
1.1 虚拟内存地址空间结构体LosVmSpace
typedef struct VmSpace {
LOS_DL_LIST node; /**< 地址空间双向链表 */
LosRbTree regionRbTree; /**< 地址区间的红黑树根节点 */
LosMux regionMux; /**< 地址区间的红黑树的互斥锁 */
VADDR_T base; /**< 地址空间开始地址 */
UINT32 size; /**< 地址空间大小 */
VADDR_T heapBase; /**< 地址空间的堆开始地址heapBase */
VADDR_T heapNow; /**< 地址空间的堆开始地址heapNow */
LosVmMapRegion *heap; /**< 地址空间的地址区间 */
VADDR_T mapBase; /**< 地址空间的映射区开始地址 */
UINT32 mapSize; /**< 地址空间的映射区大小 */
LosArchMmu archMmu; /**< 地址空间的MMU结构体 */
#ifdef LOSCFG_DRIVERS_TZDRIVER
VADDR_T codeStart; /**< 用户进程代码区开始地址 */
VADDR_T codeEnd; /**< 用户进程代码区结束地址 */
#endif
} LosVmSpace;
1.2 虚拟内存地址区间LosVmMapRegion
typedef struct VmMapRange {
VADDR_T base; /**< 虚拟内存地址区间开始地址 */
UINT32 size; /**< 虚拟内存地址区间大小 */
} LosVmMapRange;
......
struct VmMapRegion;
typedef struct VmMapRegion LosVmMapRegion;
......
struct VmMapRegion {
LosRbNode rbNode; /**< 地址区间红黑树节点 */
LosVmSpace *space; /**< 地址区间所在的地址空间 */
LOS_DL_LIST node; /**< 地址区间双向链表 */
LosVmMapRange range; /**< 地址区间地址范围 */
VM_OFFSET_T pgOff; /**< 地址区间页偏移 */
UINT32 regionFlags; /**< 地址区间标记: cow, user_wired */
UINT32 shmid; /**< 共享地址区间编号 */
UINT8 forkFlags; /**< 地址区间fork标记: COPY, ZERO, */
UINT8 regionType; /**< 地址区间类型: ANON, FILE, DEV */
union {
struct VmRegionFile {
unsigned int fileMagic;
struct file *file;
const LosVmFileOps *vmFOps;
} rf;
struct VmRegionAnon {
LOS_DL_LIST node; /**< 地址区间类型的双向链表 */
} ra;
struct VmRegionDev {
LOS_DL_LIST node; /**< 地址区间类型的双向链表 */
const LosVmFileOps *vmFOps;
} rd;
} unTypeData;
};
2、 虚拟内存相关的宏定义
文件kernel/base/inc