OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5212|回复: 1

请教lwip中的mem_malloc函数

[复制链接]

24

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2013-3-11
在线时间
22 小时
发表于 2013-9-17 19:37:14 | 显示全部楼层 |阅读模式

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
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2013-9-17 21:22:56 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 18:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表