zoukankan      html  css  js  c++  java
  • 【原译】简单的Malloc实现

    免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作!

    原文链接地址:http://os-blog.com/basic-malloc-implementation/

       已经有很多不同的,很强大的malloc的具体实现,比如tcmallocptmallocdlmalloc, and jemalloc,但是,在我们不加思索的使用这些之前,考虑一下如果实现一个基本的简单的malloc函数是非常有用的。

     现在,一般来说,我们可以实现malloc使得对malloc的调用将会被映射到系统调用sbrk上,sbrk(n)将会移动程序中断的位置-也就是程序的data段的最后。-偏移n个字节,这意味着,n个字节的内存就被分配给了当前程序

    我们最终的实现大概看起来会像这样

    void* malloc (unsigned n) 
    {
    return sbrk(n);
    }

    然而,调用一次sbrk是非常昂贵的。因此,如果我们的malloc实现,通过一次sbrk调用分配到了一块很大的内存块,当需要的时候再把这块内存分成更小的部分,相比不论什么时候需要分配了就去调用malloc,将会更加高效一些。

    记住,当申请到的内存已经用完的时候,malloc将不得不调用一次sbrk,此时,新申请到的大块内存将和原来的大块内存不是连续的。

    另外,我们将会想要重新使用那些我们已经释放的内存,因此我们的malloc实现应该保持记录当前对程序可用的内存。由于一段时间后,这些可用的小的内存块将不再连续,我们将会使用一个链表保持记录这些可用的内存块。

    最后,我们需要记录在我们的链表中,每一小块可用的内存有多大,我们给我们的链表结构添加一个size

    把上面所有的结合起来,最终,这就是一个简单的malloc的实现。

    #define MINIMUM 1024  /*通过sbrk分配的最小内存 */

    struct header {
    struct header* next; /* 指向下一个节点的指针 */
    unsigned size;
    }

    static header base; /* 链表头 */
    static header* freep = NULL; /* 空闲内存的链表 */

    void* malloc (unsigned n)
    {
    header* p, *prev;
    unsigned nunits;

    nunits = (n + sizeof(header) - 1) / sizeof(header);
    /* 检查是否还有有空闲内存的链表 */
    if ((prev = freep) == NULL) {
    base.next = freep = prev = &base;
    base.size = 0;
    }

    for (p = prev->next; ; prev = p, p = p->next) {
    /* 空间的内存是否足够? */
    if (p.size >= nunits) {
    if (p->size == nunits) /* 如果够? */
    prev->next = p->next;
    else { /* 不够就分配不够的部分 */
    p->size -= nunits;
    p += p->size;
    p->size = nunits;
    }
    freep = prev;
    return (void *)(p + 1);
    }

    if (p == freep) /* wrapped around list */
    if ((p = moremem(nunits)) == NULL)
    return NULL; /* 没有空内存 */
    }
    }

    /* 从内核中请求更多的内存 */
    header* moremem (unsigned n)
    {
    char* p;
    header* up;

    if (n < MINIMUM)
    n = MINIMUM;

    p = sbrk(n * sizeof(header));

    if (p == (char *) -1) /* 没有空闲内存 */
    return NULL;

    up = (header *) p;
    up->size = n;
    free((void *)(up + 1));

    return freep;
    }


    这就是这个函数的要点了,我就不麻烦的实现free(n)了,但是free函数所做的仅仅是把n字节大小的空间插入到链表freep适当的地方就可以了

    著作权声明:本文由http://www.cnblogs.com/lazycoding翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

  • 相关阅读:
    Mybatis在oracle批量更新
    WebService小记
    java基本排序
    ant使用
    python 集合
    amazon-aws 使用 SNS 发送短信
    Html5+ 开发APP 后台运行代码
    CentOS7 -防火墙
    java 模拟表单方式提交上传文件
    修改pom项目版本 jenkins 关联 shell命令
  • 原文地址:https://www.cnblogs.com/lazycoding/p/2310409.html
Copyright © 2011-2022 走看看