lwip—mem_init和mem_malloc詳解

來源:互聯網
上載者:User

標籤:blog   http   get   使用   資料   2014   

<pre name="code" class="cpp">#define MEM_ALIGNMENT           4//對齊為4位元組對齊#ifndef LWIP_MEM_ALIGN_SIZE#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) //實現待分配資料空間的記憶體對齊#endif#ifndef LWIP_MEM_ALIGN//地址對齊,對齊也為4位元組對齊#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))#endif/* MEM_SIZE: the size of the heap memory. If the application will senda lot of data that needs to be copied, this should be set high. */#define MEM_SIZE                (8*1024)//堆的總空間大小,此後在這個基礎上劃分堆,將在這個空間進行記憶體配置,記憶體塊結構體和資料都是在這個空間上的//mem為記憶體塊的結構體,next;,prev都為記憶體塊索引struct mem {  /** index (-> ram[next]) of the next struct *///ram為堆的首地址,相當於數組的首地址,索引基地址  mem_size_t next;//next為下一個記憶體塊的索引  /** index (-> ram[next]) of the next struct */  mem_size_t prev;//prev為前一個記憶體塊的索引  /** 1: this area is used; 0: this area is unused */  u8_t used;//標誌此記憶體塊已被分配};static struct mem *ram_end;/** All allocated blocks will be MIN_SIZE bytes big, at least! * MIN_SIZE can be overridden to suit your needs. Smaller values save space, * larger values could prevent too small blocks to fragment the RAM too much. */#ifndef MIN_SIZE#define MIN_SIZE             12//記憶體塊大小的最小限制,不能小於12#endif /* MIN_SIZE *//* some alignment macros: we define them here for better source code layout */#define MIN_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MIN_SIZE)//將MIN_SIZE按4位元組對齊,即把12按4位元組對齊#define SIZEOF_STRUCT_MEM    LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))//將mem大小按4位元組對齊#define MEM_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MEM_SIZE)//將堆的總空間按4位元組對齊,MEM_SIZE在前面,為8*1024//記憶體對齊解釋看我的博文:http://blog.csdn.net/lg2lh/article/details/34853883/** the heap. we need one struct mem at the end and some room for alignment */static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];//實際開的堆記憶體空間,MEM_SIZE_ALIGNED為對齊後的資料空間為8192//堆記憶體的大小為MEM_SIZE_ALIGNED+(2*SIZEOF_STRUCT_MEM)+MEM_ALIGNMENT=8192+2*MEN結構體的大小+4voidmem_init(void){  struct mem *mem;//定義一個mem結構體指標變數  LWIP_ASSERT("Sanity check alignment",    (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);  /* align the heap */  ram = LWIP_MEM_ALIGN(ram_heap);//將堆空間首地址ram_heap按4位元組地址對齊  /* initialize the start of the heap */  mem = (struct mem *)ram;//將堆空間ram 首地址強制轉換成mem結構體類型,作為首個記憶體塊,但這個記憶體塊還未使用  mem->next = MEM_SIZE_ALIGNED;//把首個記憶體塊的next指標指向了堆空間的最後一個地址(MEM_SIZE_ALIGNED為8*1024),後面實際在mem_malloc時會動態調整next索引,//從而得到實際分配記憶體空間即為 mem->next減去該記憶體塊mem的地址//待分配記憶體塊的next索引總是指向堆空間最後,好像也不一定,但是按照思路是這樣的。  mem->prev = 0;//初始化,因為是第一個記憶體塊,所以前一個記憶體塊不存在,故初始化為0  mem->used = 0;//該記憶體塊沒有被分配,待分配狀態  /* initialize the end of the heap */  ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];//例化一個堆空間末尾記憶體塊,該記憶體塊指向最後一個地址,標誌結尾用的已被分配,不可再分配了  ram_end->used = 1;//該記憶體塊已被分配  ram_end->next = MEM_SIZE_ALIGNED;//因為後續再無記憶體塊故,next索引指向最後,即自己  ram_end->prev = MEM_SIZE_ALIGNED;//這個我也不知道啊  mem_sem = sys_sem_new(1);  /* initialize the lowest-free pointer to the start of the heap */  lfree = (struct mem *)ram;//初始化空閑對指標,此時首個記憶體塊是閒置  MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);}void *mem_malloc(mem_size_t size){  mem_size_t ptr, ptr2;  struct mem *mem, *mem2;#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT  u8_t local_mem_free_count = 0;#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */  LWIP_MEM_ALLOC_DECL_PROTECT();  if (size == 0) {    return NULL;  }//size為0的話返回null 分配不成功  /* Expand the size of the allocated memory region so that we can     adjust for alignment. */  size = LWIP_MEM_ALIGN_SIZE(size);//將待分配資料按4位元組進行對齊  if(size < MIN_SIZE_ALIGNED) { //如果待分配空間小於MIN_SIZE_ALIGNED(12),則返回分配空間也要為12,最小分配空間為12    /* every data block must be at least MIN_SIZE_ALIGNED long */    size = MIN_SIZE_ALIGNED;  }  if (size > MEM_SIZE_ALIGNED) {//如果待分配空間大於MEM_SIZE_ALIGNED(8*1024),超出堆空間,則返回NULL,無法分配    return NULL;  }  /* protect the heap from concurrent access */  sys_arch_sem_wait(mem_sem, 0);  LWIP_MEM_ALLOC_PROTECT();//未定義#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT  /* run as long as a mem_free disturbed mem_malloc */  do {    local_mem_free_count = 0;#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */    /* Scan through the heap searching for a free block that is big enough,     * beginning with the lowest free block.     *///ptr初值=空閑記憶體塊地址與堆記憶體首地址之差,如果ptr+size小於堆空間總大小8*1024,則可實現相應大小//的記憶體塊分配,其中ptr實際為已指派了的空間大小,size為待分配的空間大小,兩個和一定要小於總空間,才可以實現分配.//判斷完成後,將ptr賦值為該記憶體塊next所指地址    for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;         ptr = ((struct mem *)&ram[ptr])->next) {//將待分配的這個記憶體空間初始化為記憶體塊結構體   mem = (struct mem *)&ram[ptr];#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT //未定義      mem_free_count = 0;      LWIP_MEM_ALLOC_UNPROTECT();      /* allow mem_free to run */      LWIP_MEM_ALLOC_PROTECT();      if (mem_free_count != 0) {        local_mem_free_count = mem_free_count;      }      mem_free_count = 0;#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT *///ptr為已指派了的記憶體空間//後面你會發現,待分配記憶體塊的mem->next始終指向堆空間的最後,即MEM_SIZE_ALIGNED。//記憶體塊未被使用,此時mem為待分配記憶體塊,故mem->next指向MEM_SIZE_ALIGNED,//剩餘分配空間(MEM_SIZE_ALIGNED-已指派空間-MEM結構體大小)要大於要待分配空間size      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 *///剩餘分配空間(MEM_SIZE_ALIGNED-已指派空間-2*MEM結構體大小-12)//要大於要待分配空間size,則才可以進行記憶體配置。        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指向新的待分配記憶體空間          ptr2 = ptr + SIZEOF_STRUCT_MEM + size;           /* create mem2 struct *///mem2為新的待分配記憶體塊結構體          mem2 = (struct mem *)&ram[ptr2]; //新的記憶體塊mem2未被使用          mem2->used = 0;//新的待分配的記憶體塊mem2的next索引指向堆空間的最後,即MEM_SIZE_ALIGNED           mem2->next = mem->next;//而新的記憶體塊的prev索引是我們這次正在分配的模組索引,即ptr           mem2->prev = ptr;          /* and insert it between mem and mem->next *///把本次分配的mem記憶體塊的next索引重新置放,指向新的待分配的模組的索引,不再指向堆空間最後          mem->next = ptr2;          mem->used = 1;//本記憶體塊被使用//我之前分析的都是新的待分配記憶體塊next索引應該始終指向堆空間最後的,這裡竟然判斷了,可能存在不指向最後的情況//具體原因還沒分析。如果新的待分配記憶體塊mem2的next索引未指向最後,則需要將它所指向的索引記憶體塊的prev索引指向 //他自己ptr2。          if (mem2->next != MEM_SIZE_ALIGNED) {            ((struct mem *)&ram[mem2->next])->prev = ptr2;          }          MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));        } else {//如果沒有滿足對應if條件,則直接分配完改記憶體塊即可,也不用指向下一個待分配的記憶體塊,因為沒有空間可以再分配了          /* (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) {//將空閑指標索引指向新的待分配記憶體塊索引ram[lfree->next],即ptr2          /* Find next free block after mem and update lowest free pointer */          while (lfree->used && lfree != ram_end) {            LWIP_MEM_ALLOC_UNPROTECT();            /* prevent high interrupt latency... */            LWIP_MEM_ALLOC_PROTECT();            lfree = (struct mem *)&ram[lfree->next];          }          LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));        }        LWIP_MEM_ALLOC_UNPROTECT();        sys_sem_signal(mem_sem);        LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",         (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);        LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",         ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);        LWIP_ASSERT("mem_malloc: sanity check alignment",          (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);        return (u8_t *)mem + SIZEOF_STRUCT_MEM;//返回分配結果,即已指派記憶體塊資料空間的首地址。      }    }#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT    /* if we got interrupted by a mem_free, try again */  } while(local_mem_free_count != 0);#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */  LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));  MEM_STATS_INC(err);  LWIP_MEM_ALLOC_UNPROTECT();  sys_sem_signal(mem_sem);  return NULL;}


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.