[cpp] view plain copy
#define MEM_ALIGNMENT
//對齊方式為4字節對齊
#ifndef LWIP_MEM_ALIGN_SIZE
#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
//實(shí)現待分配數據空間的內存對齊
#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 send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE (8*1024)
//堆的總空間大小,此后在這個(gè)基礎上劃分堆,將在這個(gè)空間進(jìn)行內存分配,內存塊結構體和數據都是在這個(gè)空間上的
//mem為內存塊的結構體,next;,prev都為內存塊索引
struct mem {
/** index (-> ram[next]) of the next struct */ //ram為堆的首地址,相當于數組的首地址,索引基地址
mem_size_t next; //next為下一個(gè)內存塊的索引
/** index (-> ram[next]) of the next struct */
mem_size_t prev; //prev為前一個(gè)內存塊的索引
/** 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];
//實(shí)際開(kāi)的堆內存空間,MEM_SIZE_ALIGNED為對齊后的數據空間為8192
//堆內存的大小為MEM_SIZE_ALIGNED+(2*SIZEOF_STRUCT_MEM)+MEM_ALIGNMENT=8192+2*MEN結構體的大小+4
void
mem_init(void)
{
struct mem *mem;
//定義一個(gè)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結構體類(lèi)型,作為首個(gè)內存塊,但這個(gè)內存塊還未使用
mem->next = MEM_SIZE_ALIGNED;
//把首個(gè)內存塊的next指針指向了堆空間的最后一個(gè)地址(MEM_SIZE_ALIGNED為8*1024),后面實(shí)際在mem_malloc時(shí)會(huì )動(dòng)態(tài)調整next索引,
//從而得到實(shí)際分配內存空間即為 mem->next減去該內存塊mem的地址
//待分配內存塊的next索引總是指向堆空間最后,好像也不一定,但是按照思路是這樣的。
mem->prev = 0;
//初始化,因為是第一個(gè)內存塊,所以前一個(gè)內存塊不存在,故初始化為0
mem->used = 0;
//該內存塊沒(méi)有被分配,待分配狀態(tài)
/* initialize the end of the heap */
ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];
//例化一個(gè)堆空間末尾內存塊,該內存塊指向最后一個(gè)地址,標志結尾用的已被分配,不可再分配了
ram_end->used = 1;
//該內存塊已被分配
ram_end->next = MEM_SIZE_ALIGNED;
//因為后續再無(wú)內存塊故,next索引指向最后,即自己
ram_end->prev = MEM_SIZE_ALIGNED;
//這個(gè)我也不知道啊
mem_sem = sys_sem_new(1);
/* initialize the lowest-free pointer to the start of the heap */
lfree = (struct mem *)ram;
//初始化空閑對指針,此時(shí)首個(gè)內存塊是空閑的
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的話(huà)返回null 分配不成功
/* Expand the size of the allocated memory region so that we can
adjust for alignment. */
size = LWIP_MEM_ALIGN_SIZE(size);
//將待分配數據按4字節進(jìn)行對齊
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,無(wú)法分配
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,則可實(shí)現相應大小
//的內存塊分配,其中ptr實(shí)際為已分配了的空間大小,size為待分配的空間大小,兩個(gè)和一定要小于總空間,才可以實(shí)現分配.
//判斷完成后,將ptr賦值為該內存塊next所指地址
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
ptr = ((struct mem *)&ram[ptr])->next) {
//將待分配的這個(gè)內存空間初始化為內存塊結構體
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為已分配了的內存空間
//后面你會(huì )發(fā)現,待分配內存塊的mem->next始終指向堆空間的最后,即MEM_SIZE_ALIGNED。
//內存塊未被使用,此時(shí)mem為待分配內存塊,故mem->next指向MEM_SIZE_ALIGNED,
//剩余分配空間(MEM_SIZE_ALIGNED-已分配空間-MEM結構體大?。┮笥谝峙淇臻gsize
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,則才可以進(jìn)行內存分配。
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索引應該始終指向堆空間最后的,這里竟然判斷了,可能存在不指向最后的情況
//具體原因還沒(méi)分析。如果新的待分配內存塊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 {//如果沒(méi)有滿(mǎn)足對應if條件,則直接分配完改內存塊即可,也不用指向下一個(gè)待分配的內存塊,因為沒(méi)有空間可以再分配了
/* (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;
聯(lián)系客服