(原创)RTOS-RTX分析系列之格子内存

2017/07/19 RTX

简介

有人问既然有了链式内存管理,干嘛还要搞一个格子内存?其实这也算是RTOS的一个专用的特性吧,在高级的系统上是没有这种内存管理的, 这里主要是给OS系统中每个结构体分配内存,由于大小相对固定,为了内存使用紧凑有效,才出现这种内存管理方式。

关键结构

和链式内存差不多,也就一个结构体:

typedef struct OS_BM {
  void *free;                     /* Pointer to first free memory block      */
  void *end;                      /* Pointer to memory block end             */
  U32  blk_size;                  /* Memory block size                       */
} *P_BM;

由上可以看出,它又不像链式内存,因为它仅仅只是个内存管理的头部,内存申请都是后面依次获取大小一样的块。

关键代码

主要是两个函数:

  1. 初始化

  2. 格子内存申请

_init_box

	/*--------------------------- _init_box -------------------------------------*/

	int _init_box  (void *box_mem, U32 box_size, U32 blk_size) {
	  /* Initialize memory block system, returns 0 if OK, 1 if fails. */
	  void *end;
	  void *blk;
	  void *next;
	  U32  sizeof_bm;

	  /* Create memory structure. */
	  if (blk_size & BOX_ALIGN_8) {
	    /* Memory blocks 8-byte aligned. */ 
	    blk_size = ((blk_size & ~BOX_ALIGN_8) + 7) & ~7;
	    sizeof_bm = (sizeof (struct OS_BM) + 7) & ~7;
	  }
	  else {
	    /* Memory blocks 4-byte aligned. */
	    blk_size = (blk_size + 3) & ~3;
	    sizeof_bm = sizeof (struct OS_BM);
	  }
	  if (blk_size == 0) {
	    return (1);
	  }
	  if ((blk_size + sizeof_bm) > box_size) {
	    return (1);
	  }
	  /* Create a Memory structure. */
	  blk = ((U8 *) box_mem) + sizeof_bm;
	  ((P_BM) box_mem)->free = blk;
	  end = ((U8 *) box_mem) + box_size;
	  ((P_BM) box_mem)->end      = end;
	  ((P_BM) box_mem)->blk_size = blk_size;

	  /* Link all free blocks using offsets. */
	  end = ((U8 *) end) - blk_size;
	  while (1)  {
	    next = ((U8 *) blk) + blk_size;
	    if (next > end)  break;
	    *((void **)blk) = next;
	    blk = next;
	  }
	  /* end marker */
	  *((void **)blk) = 0;
	  return (0);
	}

*rt_alloc_box

	/*--------------------------- rt_alloc_box ----------------------------------*/

	void *rt_alloc_box (void *box_mem) {
	  /* Allocate a memory block and return start address. */
	  void **free;
	#ifndef __USE_EXCLUSIVE_ACCESS
	  int  irq_dis;

	  irq_dis = __disable_irq ();
	  free = ((P_BM) box_mem)->free;
	  if (free) {
	    ((P_BM) box_mem)->free = *free;
	  }
	  if (!irq_dis) __enable_irq ();
	#else
	  do {
	    if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0) {
	      __clrex();
	      break;
	    }
	  } while (__strex((U32)*free, &((P_BM) box_mem)->free));
	#endif
	  return (free);
	}

关键实现

我画了张图来剖析它的结构:

img

上面的图就很清晰了,实际上该结构有缺陷,因为申请给用户使用的内存范围包括途中的p指针,因此一旦用户改写了这个指针, 再申请内存。((P_BM) box_mem)->free = *free;这行代码执行就会出错。

不过一般都是在初始化时申请一次就基本不再使用了,这倒是无影响。


知识共享许可协议
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。

站内搜索

    撩我备注-博客

    joinee

    目录结构