lwip中内存堆组织结构如图所示,下面是mem_malloc的关键代码:
void *mem_malloc(mem_size_t size)
{
mem_size_t ptr, ptr2;
struct mem *mem, *mem2;
if (size == 0)
{
return NULL;
}
/* Expand the size of the allocated memory region so that we can
adjust for alignment. */
size = LWIP_MEM_ALIGN_SIZE(size);
if(size < MIN_SIZE_ALIGNED)
{
/* every data block must be at least MIN_SIZE_ALIGNED long */
size = MIN_SIZE_ALIGNED;
}
if (size > MEM_SIZE_ALIGNED)
{
return NULL;
}
/* protect the heap from concurrent access */
sys_arch_sem_wait(mem_sem, 0);
/* Scan through the heap searching for a free block that is big enough,
* beginning with the lowest free block.
*/
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;ptr = ((struct mem *)&ram[ptr])->next)
{
mem = (struct mem *)&ram[ptr];
if ((!mem->used) &&(mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size)
{
/* mem is not used and at least perfect fit is possible:
* mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED))
{
/* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
* at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
* -> split large block, create empty remainder,
* remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
* mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
* struct mem would fit in but no data between mem2 and mem2->next
* @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
* region that couldn't hold data, but when mem->next gets freed,
* the 2 regions would be combined, resulting in more free memory
*/
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
/* create mem2 struct */
mem2 = (struct mem *)&ram[ptr2];
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;
/* and insert it between mem and mem->next */
mem->next = ptr2;
mem->used = 1;
if (mem2->next != MEM_SIZE_ALIGNED)
{
((struct mem *)&ram[mem2->next])->prev = ptr2;
}
MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
}
else
{
/* (a mem2 struct does no fit into the user data space of mem and mem->next will always
* be used at this point: if not we have 2 unused structs in a row, plug_holes should have
* take care of this).
* -> near fit or excact fit: do not split, no mem2 creation
* also can't move mem->next directly behind mem, since mem->next
* will always be used at this point!
*/
mem->used = 1;
MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
}
if (mem == lfree)
{
/* Find next free block after mem and update lowest free pointer */
while (lfree->used && lfree != ram_end)
{
lfree = (struct mem *)&ram[lfree->next];
}
}
sys_sem_signal(mem_sem);
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
}
}
sys_sem_signal(mem_sem);
return NULL;
}
读完这个函数后,我总感觉在内存组织中一个内存块的next指针指向下一个内存块的next,但是一个内存块的prev指针指向的不是上一个内存块的prev而是上一个内存的next了。我举个例子:
ram_heap[18] 不考虑MIN_SIZE 用户申请的size为2 for循环中ptr=0 ; ptr<13 ;ptr=15 ptr2=ptr+SIZEOF_STRUCT_MEM+size=5
然后 mem2->prev=ptr
((struct mem *)&ram[mem2->next])->prev = ptr2;
这样prev指向的都是上一个内存块的next不是prev啊?谢谢指点了......谢谢!!!!!!
ram[0] 0x00 next <-lfree
0x01 prev
0x02 used
0x03
0x04
0x05 next <-ptr2
0x06 prev
0x07 used
...............
........
|