Î壺mallocµÄʵÏÖ£º
·ÖÎöÍêFAµÄ²Ù×÷Ö®ºó£¬¾Í¿ÉÒÔÀ´·ÖÎömallocÓëfreeµÄ¾ßÌåʵÏÖÁË¡£ÏÈ·ÖÎömalloc
ÔÚ·ÖÎömalloc֮ǰ£¬ÓбØÒª·ÖÎöһϼ¸¸öÎÊÌ⣺
1£º´ÓÉÏÃæ__heap_free_area_allocº¯ÊýµÄ·ÖÎö¿ÉÒÔ¿´µ½¡£·ÖÅäÄÚ´æÊ±£¬Ö»Êǵ÷ÕûÁË¿ÕÏÐÇøµÄ´óС»òÕßÊÇ·ÖÅäÁËÕû¸ö¿ÕÏÐÇø¡£ÄÇÊÍ·ÅÄÚ´æµÄʱºò£¬Ôõô²ÅÄÜÖªµÀÒªÊͷŶàÉÙÄØ¡££¨free()Öв¢Ã»ÓÐÖ¸´óС²ÎÊý£©?
2:Èç¹û¶ÑµÄ¿Õ¼ä²»¹»ÁË£¬¸ÃÔõô°ì£¿ÈçºÎÍ¢É죿
¹ØÓÚ1£ºÓÃmalloc·ÖÅäÄÚ´æµÄʱºò£¬Ëü¾³£Òª¶à·ÖÅäÒ»µã£¬ÒòΪÔÚËù·ÖµÃÄÚ´æÇ°ÃæÒª±£ÁôһС¶ÎÀ´´æ´¢Ëù·ÖÅäµÄ´óС¡£ÕâÑùÔÚÊÍ·ÅÄÚ´æµÄʱºò£¬¾ÍÄÜÕÒµ½ÒªÊͷŵĴóСÁË¡£ÈçͼËùʾ£º
MALLOC_SIZE (mem)£ºÓÃÀ´·µ»ØËù·ÖµÃµÄÆðʼµØÖ·ÎªmemµÄÄÚ´æ¿é´óС
MALLOC_BASE (mem)£ºÓÃÀ´¼ÆËãËù·ÖÅäµÄÆðʼµØÖ·ÎªmemµÄÄÚ´æ¿éËù¶ÔÓ¦µÄʵ¼ÊµØÖ·
ÆäʵMALLOC_SIZE (mem)Êǽ«µØÖ·memÍ˺óMALLOC_HEADER_SIZE¸öµ¥Î»£¬È»ºóÔÙȡֵ£¬¾ÍÄܵõ½´óСÁË¡£
¶ÔÓÚ¶þ£º¿ÉÒÔµ÷ÓÃbrk()»òÕßmmapÀ´À©Õ¹Êý¾Ý¶Î¡£¹ØÓÚÕⲿ·Ý£¬ÒÔºóÎÒÔÙ¸ø³öרÌâ·ÖÎö¡£
ÖÕÓÚ¿ÉÒÔµ½¾ßÌåµÄ´úÂëʵÏÖÁË£º
malloc (size_t size)
{
//ÂÔ¹ýµ÷ÊÔ´úÂë
#ifdef MALLOC_DEBUGGING
static int debugging_initialized = 0;
if (! debugging_initialized)
{
debugging_initialized = 1;
__malloc_debug_init ();
}
if (__malloc_check)
__heap_check (&__malloc_heap, "malloc");
#endif
//²ÎÊýÓÐЧÐÔ¼ì²â¡£ÕâÀïûÓмì²â²ÎÊýΪ¸ºµÄÇé¿ö
if (size == 0)
return 0;
return malloc_from_heap (size, &__malloc_heap);
}
º¯ÊýתÈëmalloc_from_heap (size, &__malloc_heap)
ËüµÄʵÏÖÈçÏ£º
//´«Èë²ÎÊý£º
//size:ÏëÒª·ÖÅäµÄÄÚ´æ´óС¡£heap£º¼´Îª__malloc_heap
static void *
malloc_from_heap (size_t size, struct heap *heap)
{
void *mem;
MALLOC_DEBUG (1, "malloc: %d bytes", size);
/* Include extra space to record the size of the allocated block. */
//ʵ¼ÊÒª·ÖÅäµÄ´óС£¬¼ûÇ°ÃæµÄ·ÖÎö
size += MALLOC_HEADER_SIZE;
//Ϊ·ÀÖ¹¾ºÌ¬£¬¼ÓËø
__heap_lock (heap);
/* First try to get memory that's already in our heap. */
//Ê×Ïȳ¢ÊÔ´Óheap·ÖÅäÄÚ´æ.Õ⺯Êý¼ûÇ°ÃæµÄ·ÖÎö
mem = __heap_alloc (heap, &size);
//½âËø
__heap_unlock (heap);
if (unlikely (! mem))
{
//Èç¹û·ÖÅäʧ°Ü£¬ÄǾÍ˵Ã÷¿ÕÏÐÇø²»×㣬ÏòÄÚºËÉêÇë
void *block;
//¼ÆËãÒªÏòÄÚºËÉêÇëµÄ´óС£¬ÖÁÉÙҪΪһ¸öpage£¬¼´4096
size_t block_size
= (size < MALLOC_HEAP_EXTEND_SIZE
? MALLOC_HEAP_EXTEND_SIZE
: MALLOC_ROUND_UP_TO_PAGE_SIZE (size));
/* Allocate the new heap block. */
//Á½ÖÖ·½Ê½£¬Ò»ÖÖÊÇsbrk() ÁíÒ»ÖÖÊÇmmap£¨£©¡£ºóÃæ×öΪһ¸öרÌâ½éÉÜ
#ifdef MALLOC_USE_SBRK
__malloc_lock_sbrk ();
/* Use sbrk we can, as it's faster than mmap, and guarantees
contiguous allocation. */
block = sbrk (block_size);
if (likely (block != (void *)-1))
{
/* Because sbrk can return results of arbitrary
alignment, align the result to a MALLOC_ALIGNMENT boundary. */
long aligned_block = MALLOC_ROUND_UP ((long)block, MALLOC_ALIGNMENT);
if (block != (void *)aligned_block)
/* Have to adjust. We should only have to actually do this
the first time (after which we will have aligned the brk
correctly). */
{
/* Move the brk to reflect the alignment; our next allocation
should start on exactly the right alignment. */
sbrk (aligned_block - (long)block);
block = (void *)aligned_block;
}
}
__malloc_unlock_sbrk ();
#else /* !MALLOC_USE_SBRK */
/* Otherwise, use mmap. */
block = mmap (0, block_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, 0, 0);
#endif /* MALLOC_USE_SBRK */
if (likely (block != (void *)-1))
{
#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__)
struct malloc_mmb *mmb, *prev_mmb, *new_mmb;
#endif
MALLOC_DEBUG (1, "adding system memroy to heap: 0x%lx - 0x%lx (%d bytes)",
(long)block, (long)block + block_size, block_size);
/* Get back the heap lock. */
__heap_lock (heap);
/* Put BLOCK into the heap. */
//½«ÉêÇëµÄÄÚ´æ¼ÓÈëheap
__heap_free (heap, block, block_size);
MALLOC_DEBUG_INDENT (-1);
/* Try again to allocate. */
//ÖØÐÂÏòheapÉêÇëÄںˣ¬ÒòΪ´ËʱÒѾÓÐ×ã¹»µÄ¿ÕÏÐÄÚ´æÁË
mem = __heap_alloc (heap, &size);
__heap_unlock (heap);
#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__)
/* Insert a record of BLOCK in sorted order into the
__malloc_mmapped_blocks list. */
for (prev_mmb = 0, mmb = __malloc_mmapped_blocks;
mmb;
prev_mmb = mmb, mmb = mmb->next)
if (block < mmb->mem)
break;
new_mmb = malloc_from_heap (sizeof *new_mmb, &__malloc_mmb_heap);
new_mmb->next = mmb;
new_mmb->mem = block;
new_mmb->size = block_size;
if (prev_mmb)
prev_mmb->next = new_mmb;
else
__malloc_mmapped_blocks = new_mmb;
MALLOC_MMB_DEBUG (0, "new mmb at 0x%x: 0x%x[%d]",
(unsigned)new_mmb,
(unsigned)new_mmb->mem, block_size);
#endif /* !MALLOC_USE_SBRK && __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */
}
}
if (likely (mem))
/* Record the size of the block and get the user address. */
{
//ÒѾ·ÖµÃÁËÄڴ棬µ÷Õû·ÖµÃµÄÄڴ棬Áô³öд´óСµÄ¿Õ¼ä£¬µ÷ÕûÒª·µ»Ø¸ø³ÌÐòµÄµØÖ·
mem = MALLOC_SETUP (mem, size);
MALLOC_DEBUG (-1, "malloc: returning 0x%lx (base:0x%lx, total_size:%ld)",
(long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem));
}
else
MALLOC_DEBUG (-1, "malloc: returning 0");
return mem;
}
¸ú×ÙÒ»ÏÂMALLOC_SETUP (mem, size):
#define MALLOC_SETUP(base, size) \
(MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE))
#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size))
MALLOC_SET_SIZE,½«´óСдÈëÄڴ濪ʼµÄǰһ²¿·Ý¡£
Base+ MALLOC_HEADER_SIZE:µØÖ·ÉÏÒÆMALLOC_HEADER_SIZE¸öµ¥Î»

