之前我自己也写过基于链表的内存分配算法,但是看了rawos的内存分配算法,还是感觉rawos写的要更好些。大家都知道,链表内存分配就是从链表中快速找到最合适的内存块分配给用户线程。因为这种分配是随机的,所以一般来说内存碎片是不可避免的。但是,我们在编写代码的时候还是应该注意内存合并的问题。这里我们为什么要介绍rawos的内存分配呢,还包括有这么几个原因,
(1)整个内存链表采用循环链表的方法,使用起来简单可靠;
(2)内存分配的时候所有节点都是连在一起的,通过标志数据判断当前数据是否已经分配;
(3)如果当前没有合适的内存,可以选择等待;
(4)代码充分考虑了合并和切分的问题;
(5)在遍历内存的时候灵活处理了中断问题,可以及时响应中断,这个比我考虑得要周到很多;
(6)代码注释丰富,只要多读几遍,是可以慢慢理解代码内容的。
整个代码的结构清晰,共四个函数,分别是创建函数、内存查找函数、内存分配函数、内存释放函数。其中在内存分配和释放的时候,都会调用到内存查找函数。
RAW_U16 raw_byte_pool_create(RAW_BYTE_POOL_STRUCT *pool_ptr, RAW_U8 *name_ptr, RAW_VOID *pool_start, RAW_U32 pool_size) { RAW_U8 *block_ptr; /* Working block pointer */ RAW_U8 byte_align_mask; #if (RAW_BYTE_FUNCTION_CHECK > 0) if (pool_ptr == 0) { return RAW_NULL_POINTER; } if (pool_start == 0) { return RAW_NULL_POINTER; } /* Check for invalid pool size. */ if (pool_size < RAW_BYTE_POOL_MIN) { return RAW_BYTE_SIZE_ERROR; } #endif byte_align_mask = sizeof(void *) - 1u; /*pool_start needs 4 bytes aligned*/ if (((RAW_U32)pool_start & byte_align_mask)){ return RAW_INVALID_ALIGN; } /*pool_size needs 4 bytes aligned*/ if ((pool_size & byte_align_mask)) { return RAW_INVALID_ALIGN; } /*Init the list*/ list_init(&pool_ptr->common_block_obj.block_list); /* Setup the basic byte pool fields. */ pool_ptr ->common_block_obj.name = name_ptr; pool_ptr ->common_block_obj.block_way = 0; pool_ptr ->raw_byte_pool_search = (RAW_U8 *) pool_start; pool_ptr ->raw_byte_pool_owner = 0; /* Initially, the pool will have two blocks. One large block at the beginning that is available and a small allocated block at the end of the pool that is there just for the algorithm. Be sure to count the available block's header in the available bytes count. */ pool_ptr ->raw_byte_pool_available = pool_size - sizeof(void *) - sizeof(RAW_U32); pool_ptr ->raw_byte_pool_fragments = 2; /* Calculate the end of the pool's memory area. */ block_ptr = ((RAW_U8 *) pool_start) + (RAW_U32) pool_size; /* Backup the end of the pool pointer and build the pre-allocated block. */ block_ptr = block_ptr - sizeof(RAW_U32); *((RAW_U32 *) block_ptr) = RAW_BYTE_BLOCK_ALLOC; block_ptr = block_ptr - sizeof(RAW_U8 *); *((RAW_U8 * *) block_ptr) = pool_start; /* Now setup the large available block in the pool. */ *((RAW_U8 * *) pool_start) = block_ptr; block_ptr = (RAW_U8 *) pool_start; block_ptr = block_ptr + sizeof(RAW_U8 *); *((RAW_U32 *) block_ptr) = RAW_BYTE_BLOCK_FREE; return RAW_SUCCESS; } |