网站首页 Cn029.Com - 西安网吧在线℡

Cn029.Com - 西安网吧在线℡ 西北地区网吧行业门户站点www.cn029.com,本站为您提供网吧维护,每日更新最新网吧技术,政策法规.为您提供各类网管软件,网吧软件,游戏更新软件,承接西部地区网吧维护,希望与您共同讨论网吧经营管理的经验!

投递文章  投稿指南 RSS订阅 西安网吧在线通告:
搜索: 您的位置西安网吧在线Linux-UxLinux精华 → 文章内容

Uclibc中的malloc机制分析(四)

  作者:网络收集   来源:chinaunix.net   更新时间:2008-4-27 5:04:29   【 】  评论:0

五: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_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 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个单位


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/51562/showart_459146.html

Tags: 网吧 硬件 价格 最新  
责任编辑:Cn029.Com
  • 请文明参与讨论,禁止漫骂攻击。 用户名:新注册) 验证码: 验证码,看不清楚?请点击刷新验证码

    分 值:100分 85分 70分 55分 40分 25分 10分 0分

    评论总数:0条,平均得分:0[ 查看全部 ] 网友评论
    关于我们 - 联系我们 - 广告服务 - 法律声明 - RSS订阅 - 网站地图 - 返回顶部