打印

请教lwip中的mem_malloc函数

[复制链接]
2755|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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
...............
........




未命名.JPG (15.6 KB )

未命名.JPG
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

79

帖子

2

粉丝