malloc

malloc函数大家都用的很多,但是具体实现可能确实没怎么考虑。

void *malloc(size_t size)

他需要做的事情和要求如下:
1.分配一段size个Bytes大小的堆空间(后来才知道是至少size大小),并返回一个void*类型的指针,指向这段空间的首地址。如果分配失败,返回NULL
2.每次分配的时候,必须是合法的地址空间,也即如何保证不会是之前分配过的。
3.便于free释放,因此必须free时候需要知道size大小,也即要和free realloc等配套使用,因此设计的DS必须兼顾

假设一段heap空间,Linux有一个break指针记录之前已经分配的空间的高地址,再高的部分就是非法地址了。因此一个toy的malloc可以借助sbrk函数来实现,

int brk(void addr);
void
sbrk(intptr_t increment);

第一个函数将break上移increment字节大小,然后返回break之前的地址

这样借助sbrk函数可以完成,但是不好free因为没有记录这些大小,以及之前的首地址

#include <sys/types.h>
#include <unistd.h>
void *malloc(size_t size)
{
    void *p;
    p = sbrk(0);
    if (sbrk(size) == (void *)-1)
        return NULL;
    return p;
}

然后考虑使用链表来实现空间分配,将malloc的空间练成linklist,因为频繁插入删除,比数组好(我之前也觉得链表没啥用的,可以看下,这个是OS的实现)
然后首次适应和最佳适应的策略还历历在目,首次适应就需要split多余的空间提高空间利用效率,防止出现假满。

#define BLOCK_SIZE 24
void *first_block=NULL;

/* other functions... */

void *malloc(size_t size) {
    t_block b, last;
    size_t s;
    /* 对齐地址 */
    s = align8(s);
    if(first_block) {
        /* 查找合适的block */
        last = first_block;
        b = find_block(&last, s);
        if(b) {
            /* 如果可以,则分裂 */
            if ((b->size - s) >= ( BLOCK_SIZE + 8))
                split_block(b, s);
            b->free = 0;
        } else {
            /* 没有合适的block,开辟一个新的 */
            b = extend_heap(last, s);
            if(!b)
                return NULL;
        }
    } else {
        b = extend_heap(NULL, s);
        if(!b)
            return NULL;
        first_block = b;
    }
    return b->data;
}

以上几乎是码代码的张洋最新的blog笔记,新鲜出炉,学习一下,面试可能探讨会涉及~~~~
http://blog.codinglabs.org/articles/a-malloc-tutorial.html

Posted by richard爱闹 - 8月 19 2014
如需转载,请注明: 本文来自 Richard