鸿蒙内核源码分析 (内存池管理) | 如何高效切割合并内存块

动态分配

系列篇将动态分配分成上下两篇,本篇为下篇,阅读之前建议翻看上篇。

  • 鸿蒙内核源码分析(TLFS算法) 结合图表从理论视角说清楚 TLFS 算法
  • 鸿蒙内核源码分析(内存池管理) 结合源码说清楚鸿蒙内核动态内存池实现过程,个人认为这部分代码很精彩,简洁高效,尤其对空闲节点和已使用节点的实现令人称奇。

为了便于理解源码,站长画了以下图,图中列出主要结构体,位图,分配和释放信息,逐一说明。

  • 请将内存池想成一条画好了网格虚线的大白纸,会有两种角色往白纸上画东西,一个是内核画管理数据,一个外部程序画业务数据,内核先画,外部程序想画需申请大小,申请成功内核会提供个地址给外部使用,例如申请20个格子,成功后内核返回一个(5,8)坐标,表示从第五行第八列开始往后的连续20个格子你可以使用。用完了释放只需要告诉内核一个坐标(5,8)而不需要大小,内核就知道回收多少格子。但内核凭什么知道要释放多少个格子呢 ? 一定有个格子给记录下来了对不对,实际中存大小的格子坐标就是(5,7)。其值是在申请的时候或更早的时候填进去的。而且不一定是20,但一定不小于20。如果您能完全理解以上这段话,那可能已经理解了内存池的管理的方式,不用往下看了。

内存池 | OsMemPoolHead

/// 内存池头信息
struct OsMemPoolHead {
    struct OsMemPoolInfo info; ///< 记录内存池的信息
    UINT32 freeListBitmap[OS_MEM_BITMAP_WORDS]; ///< 空闲位图 int[7] = 32 * 7 = 224
    struct OsMemFreeNodeHead *freeList[OS_MEM_FREE_LIST_COUNT];///< 空闲节点链表 32 + 24 * 8 = 224  
    SPIN_LOCK_S spinlock;	///< 操作本池的自旋锁,涉及CPU多核竞争,所以必须得是自旋锁
#ifdef LOSCFG_MEM_MUL_POOL
    VOID *nextPool;	///< 指向下一个内存池 OsMemPoolHead 类型
#endif
};
/// 内存池信息
struct OsMemPoolInfo {
    VOID *pool;			///< 指向内存块基地址,仅做记录而已,真正的分配内存跟它没啥关系
    UINT32 totalSize;	///< 总大小,确定了内存池的边界
    UINT32 attr;		///< 属性 default attr: lock, not expand.
#ifdef LOSCFG_MEM_WATERLINE
    UINT32 waterLine;   /* Maximum usage size in a memory pool | 内存吃水线*/
    UINT32 curUsedSize; /* Current usage size in a memory pool | 当前已使用大小*/
#endif
}; 

解读

  • OsMemPoolInfo.pool 是整个内存池的第一个格子,里面放的是一个内存池起始虚拟地址。

  • OsMemPoolInfo.totalSize 表示这张纸有多少个格子。

  • OsMemPoolInfo.attr 表示池子还能不能再变大。

  • OsMemPoolInfo.waterLine 池子水位警戒线,跟咱三峡大坝发洪水时的警戒线 175米 类似,告知上限,水一旦漫过此线就有重大风险,waterLine一词很形象,内核很多思想真来源于生活。

  • OsMemPoolInfo.curUsedSize 所有已分配内存大小的叠加。

  • freeListBitmap 空闲位图,这是tlfs算法的一二级表示,是个长度为7的整型数组

    #define OS_MEM_BITMAP_WORDS     ((OS_MEM_FREE_LIST_COUNT >> 5) + 1) 
    #define OS_MEM_FREE_LIST_COUNT  (OS_MEM_SMALL_BUCKET_COUNT + (OS_MEM_LARGE_BUCKET_COUNT << OS_MEM_SLI)) 
    #define OS_MEM_LARGE_START_BUCKET       7 /// 大桶的开始下标
    #define OS_MEM_SMALL_BUCKET_COUNT       31 ///< 小桶的偏移单位 从 4 ~ 124 ,共32级
    #define OS_MEM_SLI                      3 ///< 二级小区间级数,
    
    

    这一坨坨的宏看着有点绕,简单说就是鸿蒙对申请大小分成两种情况

    • 第一种:小桶申请** 当小于128个字节大小的需求平均分成了([0-4],[4-8],...,[124-128])32个等级,而freeListBitmap[0]为一个UINT32,共32位刚好表示这32
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值