堆区相关代码注释

    百图画鸿蒙 + 百文说内核 + 百万注源码  => 挖透鸿蒙内核源码
    鸿蒙研究站 | http://weharmonyos.com (国内)
              | https://weharmony.github.io (国外)
    oschina | https://my.oschina.net/weharmony
    博客园 | https://www.cnblogs.com/weharmony/
    知乎 | https://www.zhihu.com/people/weharmonyos
    csdn | https://blog.csdn.net/kuangyufei
    51cto | https://harmonyos.51cto.com/column/34
    掘金 | https://juejin.cn/user/756888642000808
    公众号 | 鸿蒙研究站 (weharmonyos)
上级 5ad3f709
......@@ -79,7 +79,7 @@ struct page_mapping {
#endif
/* If the kernel malloc size is less than 16k, use heap, otherwise use physical pages */
#define KMALLOC_LARGE_SIZE (PAGE_SIZE << 2)
typedef struct VmMapRange {
typedef struct VmMapRange {//线性区范围结构体
VADDR_T base; /**< vm region base addr | 线性区基地址*/
UINT32 size; /**< vm region size | 线性区大小*/
} LosVmMapRange;
......@@ -118,7 +118,7 @@ struct VmFileOps {
struct VmMapRegion {
LosRbNode rbNode; /**< region red-black tree node | 红黑树节点,通过它将本线性区挂在VmSpace.regionRbTree*/
LosVmSpace *space; ///< 所属虚拟空间,虚拟空间由多个线性区组成
LOS_DL_LIST node; /**< region dl list | 链表节点,通过它将本线性区挂在VmSpace.regions上*/
LOS_DL_LIST node; /**< region dl list | 链表节点,通过它将本线性区挂在VmSpace.regions上 ,但最新版本没有regions了,可以删除了 */
LosVmMapRange range; /**< region address range | 记录线性区的范围*/
VM_OFFSET_T pgOff; /**< region page offset to file | 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射。*/
UINT32 regionFlags; /**< region flags: cow, user_wired | 线性区标签*/
......@@ -148,9 +148,9 @@ typedef struct VmSpace {
LosMux regionMux; /**< region list mutex lock | 虚拟空间操作红黑树互斥锁*/
VADDR_T base; /**< vm space base addr | 虚拟空间的基地址,线性区的分配范围,常用于判断地址是否在内核还是用户空间*/
UINT32 size; /**< vm space size | 虚拟空间大小*/
VADDR_T heapBase; /**< vm space heap base address | 堆区基地址,表堆区范围起点*/
VADDR_T heapNow; /**< vm space heap base now | 堆区现地址,表堆区范围终点,do_brk()直接修改堆的大小返回新的堆区结束地址, heapNow >= heapBase*/
LosVmMapRegion *heap; /**< heap region | 堆区是个特殊的线性区,用于满足进程的动态内存需求,大家熟知的malloc,realloc,free其实就是在操作这个区*/
VADDR_T heapBase; /**< vm space heap base address | 堆区基地址,指向堆区起点*/
VADDR_T heapNow; /**< vm space heap base now | 堆顶地址,指向堆区终点,do_brk()直接修改堆的大小返回新的堆区结束地址, heapNow >= heapBase*/
LosVmMapRegion *heap; /**< heap region | 传说中的堆区,用于满足进程的动态内存需求,大家熟知的malloc,realloc,free其实就是在操作这个区*/
VADDR_T mapBase; /**< vm space mapping area base | 虚拟空间映射区基地址,L1,L2表存放在这个区 */
UINT32 mapSize; /**< vm space mapping area size | 虚拟空间映射区大小,映射区是个很大的区。*/
LosArchMmu archMmu; /**< vm mapping physical memory | MMU记录<虚拟地址,物理地址>的映射情况 */
......
......@@ -188,7 +188,7 @@ ULONG_T OsRegionRbCmpKeyFn(const VOID *pNodeKeyA, const VOID *pNodeKeyB)
}
/*!
* @brief OsVmSpaceInitCommon 初始化虚拟空间,必须提供L1表的虚拟内存地址
* @brief OsVmSpaceInitCommon 初始化进程虚拟空间,必须提供L1表的虚拟内存地址
*
* @param virtTtb L1表的地址,TTB表地址
* @param vmSpace
......@@ -852,7 +852,7 @@ ERR_REGION_SPLIT:
(VOID)LOS_MuxRelease(&space->regionMux);
return status;
}
///释放用户空间的堆区
///根据指定参数范围[addr,addr+len] 释放用户空间中堆区所占用的物理内存
INT32 OsUserHeapFree(LosVmSpace *vmSpace, VADDR_T addr, size_t len)
{
LosVmMapRegion *vmRegion = NULL;
......@@ -870,7 +870,7 @@ INT32 OsUserHeapFree(LosVmSpace *vmSpace, VADDR_T addr, size_t len)
return -1;
}
if (vmRegion == vmSpace->heap) {//虚拟空间的堆区和找到的线性区虚拟地址一致,确定是找到了堆区的线性
if (vmRegion == vmSpace->heap) {//地址所在的线性区为堆
vaddr = addr;
while (len > 0) {//参数0 代表不获取 flags 信息
if (LOS_ArchMmuQuery(&vmSpace->archMmu, vaddr, &paddr, 0) == LOS_OK) {//通过虚拟地址查到物理地址
......
......@@ -180,7 +180,7 @@ VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags,
resultVaddr = vaddr;
goto MMAP_DONE;
}
//地址不在堆区
regionFlags = OsCvtProtFlagsToRegionFlags(prot, flags);//将参数flag转换Region的flag
newRegion = LOS_RegionAlloc(vmSpace, vaddr, len, regionFlags, pgoff);//分配一个线性区
if (newRegion == NULL) {
......@@ -188,7 +188,7 @@ VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags,
goto MMAP_DONE;
}
newRegion->regionFlags |= VM_MAP_REGION_FLAG_MMAP;
resultVaddr = newRegion->range.base;
resultVaddr = newRegion->range.base;//线性区基地址为分配的地址
if (LOS_IsNamedMapping(flags)) {
status = OsNamedMMap(filep, newRegion);//文件映射
......@@ -229,17 +229,17 @@ STATIC INLINE BOOL OsProtMprotectPermCheck(unsigned long prot, LosVmMapRegion *r
return ((protFlags & permFlags) == protFlags);
}
/// 收缩堆区
VOID *OsShrinkHeap(VOID *addr, LosVmSpace *space)
{
VADDR_T newBrk, oldBrk;
newBrk = LOS_Align((VADDR_T)(UINTPTR)addr, PAGE_SIZE);
oldBrk = LOS_Align(space->heapNow, PAGE_SIZE);
if (LOS_UnMMap(newBrk, (oldBrk - newBrk)) < 0) {
return (void *)(UINTPTR)space->heapNow;
newBrk = LOS_Align((VADDR_T)(UINTPTR)addr, PAGE_SIZE);//新堆顶
oldBrk = LOS_Align(space->heapNow, PAGE_SIZE);//旧堆顶
if (LOS_UnMMap(newBrk, (oldBrk - newBrk)) < 0) {//解除相差区的映射
return (void *)(UINTPTR)space->heapNow;//解除失败就持续现有的
}
space->heapNow = (VADDR_T)(UINTPTR)addr;
space->heapNow = (VADDR_T)(UINTPTR)addr;//返回新堆顶
return addr;
}
......@@ -279,14 +279,14 @@ VOID *LOS_DoBrk(VOID *addr)
PRINT_INFO("brk addr %p , size 0x%x, alignAddr %p, align %d\n", addr, size, alignAddr, PAGE_SIZE);
(VOID)LOS_MuxAcquire(&space->regionMux);
if (addr < (VOID *)(UINTPTR)space->heapNow) {
if (addr < (VOID *)(UINTPTR)space->heapNow) {//如果地址小于堆区现地址
shrinkAddr = OsShrinkHeap(addr, space);//收缩堆区
(VOID)LOS_MuxRelease(&space->regionMux);
return shrinkAddr;
}
if ((UINTPTR)alignAddr >= space->mapBase) {
VM_ERR("Process heap memory space is insufficient");
if ((UINTPTR)alignAddr >= space->mapBase) {//参数地址 大于映射区地址
VM_ERR("Process heap memory space is insufficient");//进程堆空间不足
ret = (VOID *)-ENOMEM;
goto REGION_ALLOC_FAILED;
}
......@@ -301,24 +301,24 @@ VOID *LOS_DoBrk(VOID *addr)
goto REGION_ALLOC_FAILED;
}
region->regionFlags |= VM_MAP_REGION_FLAG_HEAP;//贴上线性区类型为堆区的标签,注意一个线性区可以有多种标签
space->heap = region;//更新虚拟空间堆区为分配的线性
space->heap = region;//指定线性区为堆
}
space->heapNow = (VADDR_T)(UINTPTR)alignAddr;//更新线性区结束地址
space->heapNow = (VADDR_T)(UINTPTR)alignAddr;//更新堆区顶部位置
space->heap->range.size = size; //更新堆区大小,经此操作线性区变大或缩小了
ret = (VOID *)(UINTPTR)space->heapNow;//返回线性区最新的地址
ret = (VOID *)(UINTPTR)space->heapNow;//返回堆顶
REGION_ALLOC_FAILED:
(VOID)LOS_MuxRelease(&space->regionMux);
return ret;
}
/// 继承老线性区的标签
STATIC UINT32 OsInheritOldRegionName(UINT32 oldRegionFlags)
{
UINT32 vmFlags = 0;
if (oldRegionFlags & VM_MAP_REGION_FLAG_HEAP) {
vmFlags |= VM_MAP_REGION_FLAG_HEAP;
if (oldRegionFlags & VM_MAP_REGION_FLAG_HEAP) { //如果是从大堆区中申请的
vmFlags |= VM_MAP_REGION_FLAG_HEAP; //线性区则贴上堆区标签
} else if (oldRegionFlags & VM_MAP_REGION_FLAG_STACK) {
vmFlags |= VM_MAP_REGION_FLAG_STACK;
} else if (oldRegionFlags & VM_MAP_REGION_FLAG_TEXT) {
......
......@@ -109,7 +109,8 @@ STATIC LmsMemListNode *OsLmsCheckPoolCreate(VOID)
}
return NULL;
}
/// 将指定内存池的地址范围添加到LMS的内存检测链表上,当访问的地址在链表范围内时,LMS才进行合法性校验;
/// 且LOS_MemInit接口会调用该接口,默认将初始化的内存池挂入到检测链表中。
UINT32 LOS_LmsCheckPoolAdd(const VOID *pool, UINT32 size)
{
UINT32 intSave;
......
......@@ -48,32 +48,32 @@ extern "C" {
#define LOS_RB_RED 0
#define LOS_RB_BLACK 1
typedef struct TagRbNode {
struct TagRbNode *pstParent;
struct TagRbNode *pstRight;
struct TagRbNode *pstLeft;
ULONG_T lColor;
typedef struct TagRbNode {//节点
struct TagRbNode *pstParent; ///< 爸爸是谁 ?
struct TagRbNode *pstRight; ///< 右孩子是谁 ?
struct TagRbNode *pstLeft; ///< 左孩子是谁 ?
ULONG_T lColor; //是红还是黑节点
} LosRbNode;
typedef ULONG_T (*pfRBCmpKeyFn)(const VOID *, const VOID *);
typedef ULONG_T (*pfRBFreeFn)(LosRbNode *);
typedef VOID *(*pfRBGetKeyFn)(LosRbNode *);
typedef struct TagRbTree {
LosRbNode *pstRoot;
LosRbNode stNilT;
typedef struct TagRbTree {//红黑树控制块
LosRbNode *pstRoot;//根节点
LosRbNode stNilT;//叶子节点
LOS_DL_LIST stWalkHead;
ULONG_T ulNodes;
pfRBCmpKeyFn pfCmpKey;
pfRBFreeFn pfFree;
pfRBGetKeyFn pfGetKey;
pfRBCmpKeyFn pfCmpKey; //比较大小处理函数
pfRBFreeFn pfFree; //释放结点处理函数
pfRBGetKeyFn pfGetKey;//获取节点内容处理函数
} LosRbTree;
///记录步数
typedef struct TagRbWalk {
LOS_DL_LIST stLink;
LosRbNode *pstCurrNode;
struct TagRbTree *pstTree;
LosRbNode *pstCurrNode; //当前节点
struct TagRbTree *pstTree;//红黑树
} LosRbWalk;
// 常用于两个线性区的虚拟地址的大小和范围
#define RB_EQUAL (0) //相等
......
......@@ -124,7 +124,7 @@ STATIC VOID OsRbRightRotateNode(LosRbTree *pstTree, LosRbNode *pstY)
pstNilT->pstParent = pstParent;
return;
}
/// 红黑树调整
STATIC VOID OsRbInsertNodeFixup(LosRbTree *pstTree, VOID *pstData)
{
LosRbNode *pstParent = NULL;
......@@ -419,9 +419,9 @@ STATIC VOID OsRbInitTree(LosRbTree *pstTree)
}
pstTree->ulNodes = 0;
pstTree->pstRoot = &(pstTree->stNilT);
pstTree->stNilT.lColor = LOS_RB_BLACK;
pstTree->stNilT.pstLeft = NULL; /* Always NULL */
pstTree->pstRoot = &(pstTree->stNilT); //初始时只有一个结点
pstTree->stNilT.lColor = LOS_RB_BLACK; //默认根节点是黑色
pstTree->stNilT.pstLeft = NULL; /* Always NULL | 总是空 又叫NIL结点*/
pstTree->stNilT.pstRight = NULL; /* Always NULL */
pstTree->stNilT.pstParent = NULL; /* Not NULL when tree isn't empty */
LOS_ListInit(&pstTree->stWalkHead);
......@@ -543,7 +543,7 @@ VOID LOS_RbInsertOneNodeProcess(LosRbTree *pstTree, LosRbNode *pstParent, LosRbN
return;
}
/// 初始化进程红黑树
VOID LOS_RbInitTree(LosRbTree *pstTree, pfRBCmpKeyFn pfCmpKey, pfRBFreeFn pfFree, pfRBGetKeyFn pfGetKey)
{
if (NULL == pstTree) {
......@@ -558,7 +558,7 @@ VOID LOS_RbInitTree(LosRbTree *pstTree, pfRBCmpKeyFn pfCmpKey, pfRBFreeFn pfFree
return;
}
/// 销毁进程红黑树
VOID LOS_RbDestroyTree(LosRbTree *pstTree)
{
LosRbNode *pstNode = NULL;
......@@ -744,7 +744,7 @@ ULONG_T LOS_RbAddNode(LosRbTree *pstTree, LosRbNode *pstNew)
return FALSE;
}
pNodeKey = pstTree->pfGetKey(pstNew);
pNodeKey = pstTree->pfGetKey(pstNew);//获取线性区范围
ulSearchNode = LOS_RbGetNode(pstTree, pNodeKey, &pstX);
if (TRUE == ulSearchNode) {
return FALSE;
......
......@@ -91,6 +91,11 @@ void *SysMremap(void *oldAddr, size_t oldLen, size_t newLen, int flags, void *ne
{
return (void *)LOS_DoMremap((vaddr_t)oldAddr, oldLen, newLen, flags, (vaddr_t)newAddr);
}
/**
* @brief 修改访问权限
* @param addr
* @return void*
*/
int SysMprotect(void *vaddr, size_t len, int prot)
{
......
git add -A
git commit -m ' 同步官方最新代码 | 新增各CPU核自主管理中断
git commit -m ' 堆区相关代码注释
百图画鸿蒙 + 百文说内核 + 百万注源码 => 挖透鸿蒙内核源码
鸿蒙研究站 | http://weharmonyos.com (国内)
| https://weharmony.github.io (国外)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册