【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】 
 
     内存池设计是嵌入式系统的一个重要环节,之前我们也讨论过相关的内容。但是,看了rawos的代码之后,我觉得rawos的内存池设计更有特点。整个内存池的设计非常健壮,不但考虑了字节对齐的问题,而且还引入了等待调度机制,这是我所没有想到的。所以,在此我很愿意和大家分享这份优秀的代码。闲话不多说,我们看看rawos的mempool数据结构是什么样的,

typedef struct MEM_POOL{RAW_COMMON_BLOCK_OBJECT       common_block_obj;/* Define the number of available memory blocks in the pool.  */RAW_U32      raw_block_pool_available;/* Define the head pointer of the available block pool.  */RAW_U8      *raw_block_pool_available_list;} MEM_POOL;

内存池的结构非常简单,主要包括了通用阻塞结构、block数值,block起始指针。内存池下面可以包括若干个block,每个block的大小都是相等的,同时block之间是通过链表串联在一起的,这个我们看了后面的代码就明白了。mempool的处理函数不多,就三个,初始化、申请、释放函数。

RAW_U16  raw_block_pool_create(MEM_POOL *pool_ptr, RAW_U8  *name_ptr, RAW_U32  block_size, RAW_VOID  *pool_start, RAW_U32  pool_size){//MEM_POOL   *tail_ptr;                  /* Working block pool pointer  */RAW_U32       blocks;                     /* Number of blocks in pool    */RAW_U8        *block_ptr;                  /* Working block pointer       */RAW_U8        *next_block_ptr;             /* Next block pointer          */RAW_U8        *end_of_pool;                /* End of pool area            */RAW_U8            block_align_mask;#if (RAW_BLOCK_FUNCTION_CHECK > 0)/* Check for invalid pool size.  */if (pool_size < (block_size +  block_size) ) {return RAW_BLOCK_SIZE_ERROR;}if (pool_ptr == 0) {return RAW_NULL_OBJECT;}if (pool_start == 0) {return RAW_NULL_POINTER;}#endifblock_align_mask = sizeof(void *) - 1u;if (((RAW_U32)pool_start & block_align_mask)){                             return RAW_INVALID_ALIGN;}if ((pool_size & block_align_mask)) {   return RAW_INVALID_ALIGN;}if ((block_size & block_align_mask)) {   return RAW_INVALID_ALIGN;}/*Init the list*/list_init(&pool_ptr->common_block_obj.block_list);/* Setup the basic block pool fields.  */pool_ptr ->common_block_obj.name =  name_ptr;pool_ptr ->common_block_obj.block_way = 0;/* Calculate the end of the pool's memory area.  */end_of_pool =  (RAW_U8  *) pool_start + pool_size;/* Walk through the pool area, setting up the available block list.  */blocks =            0;block_ptr =         (RAW_U8  *) pool_start;next_block_ptr =    block_ptr + block_size;while (next_block_ptr <= end_of_pool) {blocks++;if (next_block_ptr == end_of_pool) {break;}/* Setup the link to the next block.  */*((RAW_U8  * *) block_ptr) =  next_block_ptr;/* Advance to the next block.  */block_ptr =   next_block_ptr;/* Update the next block pointer.  */next_block_ptr =  block_ptr + block_size;}/* Set the last block's forward pointer to NULL.  */*((RAW_U8  * *) block_ptr) =  0;/* Save the remaining information in the pool control block.  */pool_ptr ->raw_block_pool_available =  blocks;pool_ptr ->raw_block_pool_available_list =  (RAW_U8  *) pool_start;return RAW_SUCCESS;}

上面就是内存池的创建函数,入参共有五个参数,分别是mempool结构、名称、block大小、pool起始地址、pool大小。函数基本内容如下所示,
     (1)判断内存池、指针参数合法性;
     (2)检验指针是否n字节对齐,n取决于地址的大小;
     (3)构建block链表,前后相连,最后一个block指向NULL指针;
     (4)将pool首地址赋值给raw_block_pool_available_list,函数返回。

RAW_U16 raw_block_allocate(MEM_POOL *pool_ptr, RAW_VOID **block_ptr, RAW_U32 wait_option){RAW_U16                status;                             RAW_U8      *work_ptr;                      RAW_SR_ALLOC();#if (RAW_BLOCK_FUNCTION_CHECK > 0)if (pool_ptr == 0) {return RAW_NULL_OBJECT;}if (block_ptr == 0) {return RAW_NULL_POINTER;}if (raw_int_nesting) {if (wait_option != RAW_NO_WAIT) {return RAW_NOT_CALLED_BY_ISR;}}#endifRAW_CRITICAL_ENTER();/* Determine if there is an available block.  */if (pool_ptr ->raw_block_pool_available) {/* Yes, a block is available.  Decrement the available count.  */pool_ptr ->raw_block_pool_available--;/* Pickup the current block pointer.  */work_ptr =  pool_ptr ->raw_block_pool_available_list;/* Return the first available block to the caller.  */*((RAW_U8 **)block_ptr) =  work_ptr;/* Modify the available list to point at the next block in the pool. */pool_ptr ->raw_block_pool_available_list = *((RAW_U8 **)work_ptr);/* Set status to success.  */status =  RAW_SUCCESS;}/*if no block memory is available then do it depend wait_option*/else {  if (wait_option == RAW_NO_WAIT) { *((RAW_U8 **)block_ptr)     = 0;RAW_CRITICAL_EXIT();return RAW_NO_PEND_WAIT;}  /*system is locked so task can not be blocked just return immediately*/if (raw_sched_lock) {  *((RAW_U8 **)block_ptr)     = 0;RAW_CRITICAL_EXIT();   return RAW_SCHED_DISABLE;    }raw_pend_object(&pool_ptr->common_block_obj, raw_task_active, wait_option);RAW_CRITICAL_EXIT();raw_sched();                                             RAW_CRITICAL_ENTER();*((RAW_U8 **)block_ptr)     = 0;status = block_state_post_process(raw_task_active, block_ptr);RAW_CRITICAL_EXIT();  }return status;}

和其他的内存池申请函数不一样,这里有一个wait_option选项。也就是说,如果当前没有合适的block,那么你可以选择等待处理。一旦别的线程释放内存,你就可以得到调度继续运行了。当然你也可以不等待,一旦寻找不到合适的block,立即返回为NULL。

RAW_U16 raw_block_release(MEM_POOL *pool_ptr, RAW_VOID *block_ptr){LIST *block_list_head;RAW_U8        *work_ptr;           /* Working block pointer   */RAW_U8          need_schedule = 0;RAW_SR_ALLOC();#if (RAW_BLOCK_FUNCTION_CHECK > 0)if (block_ptr == 0) {return RAW_NULL_OBJECT;}if (pool_ptr == 0) {return RAW_NULL_OBJECT;}#endifblock_list_head = &pool_ptr->common_block_obj.block_list;RAW_CRITICAL_ENTER();work_ptr =  ((RAW_U8 *) block_ptr);if (is_list_empty(block_list_head)) {        /* Put the block back in the available list.  */*((RAW_U8  **) work_ptr) =  pool_ptr ->raw_block_pool_available_list;/* Adjust the head pointer.  */pool_ptr ->raw_block_pool_available_list =  work_ptr;        /* Increment the count of available blocks.  */pool_ptr ->raw_block_pool_available++;}else {need_schedule = 1;wake_send_msg(list_entry(block_list_head->next, RAW_TASK_OBJ, task_list),  block_ptr); }RAW_CRITICAL_EXIT();if (need_schedule) {raw_sched();}/* Return completion status.  */return RAW_SUCCESS;}

和其他的内存free函数不一样,这里的free函数多了一个wake_send_msg的功能。这也就是说,当然如果存在阻塞等待资源的线程,那么把资源送给该线程,同时把该线程唤醒,还要把need_schedule设置为1才可以。当然如果没有等待的线程,那么直接把内存插入到链表前面中即可,就是这么简单。

嵌入式操作系统内核原理和开发(等值block内存池设计)相关推荐

  1. 嵌入式操作系统内核原理和开发(固定内存分配算法)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 固定内存方式是最简单的方法,也是最容易想到的方法.所谓的固定内存,就是所有分配的内存单元都是一 ...

  2. 嵌入式操作系统内核原理和开发

    嵌入式操作系统内核原理和开发(开篇) 操作系统是很多人每天必须打交道的东西,因为在你打开电脑的一刹那,随着bios自检结束,你的windows系统已经开始运行了.如果问大家操作系统是什么?可能有的人会 ...

  3. 嵌入式操作系统内核原理和开发(总结篇)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 很多朋友都喜欢嵌入式操作系统的内容,但是如何实现和仿真这样一个系统一直是困扰我们的难题.现在郑 ...

  4. 嵌入式操作系统内核原理和开发(信号量)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 之前因为工作的原因,操作系统这块一直没有继续写下去.一方面是自己没有这方面的经历,另外一方面就 ...

  5. 嵌入式操作系统内核原理和开发(地址空间)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 不管是什么样的嵌入式cpu,它必然有自己的访问地址空间.至于这个具体的访问空间是什么,那cpu ...

  6. 嵌入式操作系统内核原理和开发(改进的链表内存分配算法)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 之前我自己也写过基于链表的内存分配算法,但是看了rawos的内存分配算法,还是感觉rawos写 ...

  7. 嵌入式操作系统内核原理和开发(消息队列)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 消息队列是线程交互的一种方法,任务可以通过消息队列来实现数据的沟通和交换.在嵌入式系统上,这可 ...

  8. 嵌入式操作系统内核原理和开发(头文件调整)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 很长一段时间,我个人对头文件的功能了解得不是很明白.虽然在平时的开发中,对于头文件也没有犯过什 ...

  9. 嵌入式操作系统内核原理和开发(基础)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在编写我们的操作系统之前,我们需要明确一些事情.比如说,这个系统的运行环境是什么?怎么编译?基 ...

最新文章

  1. 网站性能优化的三重境界
  2. MongoDB 查询 (转) 仅限于C++开发
  3. 电脑开机一会就蓝屏怎么回事_电脑蓝屏怎么回事
  4. FAL风控培训|如何用一张图了解所有特征工程的套路
  5. Linux下安装informix11.5数据库
  6. 计算机图形学在线作业,18春北交《计算机图形学》在线作业一-2
  7. ios越狱开发_隐藏Root(Cydia)图标
  8. 软著申请流程与方法详解
  9. Windows 10系统安装AutoCAD 2007
  10. docker 安装Mysql并设置自启动
  11. 重磅!!毕业将近,论文免费查重工具任你选,非常值得收藏!
  12. linux终端怎么复制粘贴某一行_如何在Linux终端中复制和粘贴文本、文件和文件夹...
  13. 单片机c语言延时程序计算,单片机 计算延时子程序执行时间
  14. 从MIT协议谈契约精神
  15. 设计Course类:处理课程信息,每门课都有一个名字以及选课的学生,要能够向/从这个课程添加/删除一个学生
  16. C/C++面试感受和经验以及面试题收藏(转)
  17. Fedora安装字体方法和Ubuntu非常不同!
  18. 2022牛客多校(十)
  19. Hi3518EV200+PS3210调试经验总结
  20. 不错的电子书搜索引擎

热门文章

  1. 单例模式 代码以及祥解
  2. 合并压缩JavaScript,开发发布两不误
  3. URL安全的Base64编码
  4. nginx 日志过滤网络爬虫
  5. 关于div的定位属性问题
  6. 类里面没有参缺省构造函数 的带来的问题
  7. 我年龄大了还学的动it吗
  8. OSO.EXE病毒专杀工具
  9. springboot整合nacos配置实现实时更新
  10. jQuery操作radio、checkbox、select 集合