ptmalloc - 第一次申请与释放大内存

ptmalloc - 第一次申请与释放大内存


glibc中malloc的代码包括了线程同步,平台兼容性等问题,但是本系列文章主要的研究对象ptmalloc。所以提供的代码都是经过简化,部分宏也会展开,能够说清楚ptmalloc的运行流程就可以了。

要点


  • 用例
  • 第一次申请大块内存
  • 第一次释放大块内存
  • 两章总结

用例


int main(void)
{
    char   *mem = malloc(0x20000);

    free(mem);

    return  -1;
}

第一次申请大块内存


为什么malloc的字节数是0x20000,而不是4096或者其他呢?4096不够大么,不够,sysmalloc代码里面有这么一段

/* 对于我的测试环境来说 */
#define DEFAULT_MMAP_THRESHOLD 0x20000

static struct malloc_par mp_ =
{
    ...
    .mmap_threshold = DEFAULT_MMAP_THRESHOLD,
    ...
};


if ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)) {
    ... /* 更多关于大块内存分配的代码 */
}

在第一次分配内存的时候,DEFAULT_MMAP_THRESHOLD就是走入分岔口的判定条件,一条分岔口已经在分配小内存那一章说过了,这次说的就是另一条道路了,这条道路看起来轻松很多了,起码要看的代码可是少很多了。直接贴上sysmalloc的代码吧

static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{
    size_t      pagesize = 0x1000;
    long        size;
    char       *mm;
    mchunkptr   p;

    size = (nb + 8 + pagesize - 1) & -pagesize;

    if (size > nb) {
        mm = (char *)mmap(NULL, size,
            PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

        if (mm != (void *)-1) {
            p = (mchunkptr)mm;
            p->mchunk_prev_size = 0;
            p->mchunk_size |= IS_MAPPED;

            mp_.n_mmaps += 1;
            mp_.max_n_mmaps = MAX(mp_.max_n_mmaps, mp_.n_mmaps);

            mp_.mmaped_mem += size;
            mp_.max_mmaped_mem = MAX(mp_.max_mmaped_mem, mp_.mmaped_mem);

            return  p + MIN_CHUNK_SIZE;
        }
    }

    return  NULL;
}

第一次释放大块内存


从上面的代码可以看到,申请大块内存是使用mmap,那么释放肯定就是用munmap了
释放的代码量更少了,就是释放,设置。Talk is cheap, show me the code

void
__libc_free(void *mem)
{
    mchunkptr   p;

    /* 这里可以告诉你,可以不用手贱尝试释放NULL,你对我不起作用 */
    if (mem == NULL) {
        return; 
    }

    p = (mchunkptr)((char *)mem - 2 * SIZE_SZ);

    if (p->mchunk_size & IS_MAPPED) {
        /* 动态调整threshold */
        mp_.mmap_threshold = chunksize (p);
        mp_.trim_threshold = 2 * mp_.mmap_threshold;

        munmap_chunk(p);

        return;
    }

    /* other code */
    ...

    return;
}

static void
munmap_chunk(mchunkptr p)
{
    size_t  size = p->mchunk_size;

    mp_.n_mmaps--;
    mp_.mmaped_mem -= size;

    /* 释放 */
    munmap(p, size);

    return;
}

两章总结


写了两篇东西了,也是时候写写总结

  • 对于malloc来说,是分为三个调用层次,__libc_malloc,调用malloc_hook和包装层,_int_malloc是预处理层,并不涉及实际的调用内存分配接口,sysmalloc是实际分配内存的地方
  • 小内存分配用sbrk分配一大块然后切割
  • 大内存分配使用mmap/munmap进行管理
  • sysmalloc的代码400+,两章已经差不多说完了,剩下的就是大头_int_malloc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值