• (转)简单的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翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

  • 相关阅读:
    使用ConfigFilter
    读取特定文件,替换第一行内容
    sqlserver,oracle,mysql等的driver驱动,url怎么写
    Excel 数字处理
    ResultMap详解
    正则表达式
    Tomasulo algorithm
    scoreboarding
    data hazard in CPU pipeline
    差分绕线间距对阻抗的影响
  • 原文地址:https://www.cnblogs.com/wuyepeng/p/9724615.html
Copyright © 2020-2023  润新知