使用mmap和munmap实现自己的malloc / free

时间:2011-12-12 14:12:29

标签: c linux memory-management x86 mmap

我已使用 malloc 免费使用 mmap 实施。现在,由于与 free 不同, munmap 也将长度作为参数,因此我将长度作为附加信息放在映射的内存中。

我的 malloc 免费的代码如下所示。我想问一下,如果这段代码是好的,或者我仍然遗漏任何东西或以错误的方式做某事。

void * malloc ( size_t size )
{
    int *plen;
    int len = size + sizeof( size ); // Add sizeof( size ) for holding length.

    plen = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );

    *plen = len;                     // First 4 bytes contain length.
    return (void*)(&plen[1]);        // Memory that is after length variable.
}

void free ( void * ptr )
{
    int *plen = (int*)ptr;
    int len;

    plen--;                          // Reach top of memory
    len = *plen;                     // Read length

    munmap( (void*)plen, len );
}

5 个答案:

答案 0 :(得分:14)

一些观察结果:

  • 您认为intsize_t具有相同的尺寸。如果你想在分配的头部存储size_t值,那你为什么不这样做呢?为什么要介绍int
  • 在内存使用和速度方面,这很可能非常低效。 mmap()有很大的开销,通常分配不能小于“页面”。大多数真正的分配器试图以各种方式避免在每个malloc()上调用操作系统级功能。
  • 如果mmap()失败,则会返回MAP_FAILEDmalloc()也是如此。因此,您需要在取消引用mmap()返回的指针之前测试该
  • 调用free(NULL)应该是有效的事情;你的实现很可能导致崩溃,因为你没有NULL - 在假设它有效之前检查参数。

答案 1 :(得分:7)

你应该,至少。

  • 检查mmap是否失败
  • 存储size_t的尺寸,而不是int。他们可能会有所不同。
  • 返回合适的对齐内存,这里的内存似乎是4字节对齐(当你向mmap的页面对齐数据添加一个int,大概是4个字节。这意味着存储需要更大对齐的值返回内存,例如双重导致性能损失,或在某些体系结构上彻底崩溃。
  • 处理NULL被传递给免费(它应该是无操作)

对于malloc实现,我还希望它至少具有基本的调试支持,例如:尝试检测双重释放,尝试检测自由无效指针,列出内存不是免费的等等。

请记住,这里的malloc实现可能非常浪费。如果malloc 10个字节,你最终将分配1个页面(4096个字节),所有这些都必须映射到物理内存,剩下的4082个字节未被使用。

答案 2 :(得分:2)

另请阅读c malloc on wikipedia并仔细研究一些真正的malloc实现,例如Doug Lea's malloc。关于这个问题有很多文献,例如: by Wolfram Gloger以及许多其他人。

@MetallicPriest:你真的应该更多地解释你在做什么(我对你的工作不是很乐观,但你可能会学到很多东西!)

答案 3 :(得分:1)

每次调用自定义malloc时都不应该调用mmap。如前所述,这样做有很大的开销。

你应该创建一个大型共享内存(例如4K),你的malloc函数只需返回你所分配的内存范围内的指针。

然后,如果你的内存不足,你就会创建另外4k的共享内存。

你只需要计算你使用多少空间并跟踪你的引用,这样就可以更容易地释放内存。

答案 4 :(得分:1)

您还应该使用-1代替0作为mmap的fd参数。

mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
  

MAP_ANONYMOUS

     

任何文件都不支持映射;其内容初始化为零。 fd和offset参数被忽略;但是,如果指定了MAP_ANONYMOUS(或MAP_ANON),某些实现要求fd为-1,便携式应用程序应确保这一点。自内核2.4以来,Linux上仅支持将MAP_ANONYMOUS与MAP_SHARED结合使用。