在C中实现隔离内存存储(malloc)

时间:2014-09-09 02:33:32

标签: c memory-management malloc

我尝试使用隔离的免费列表(使用此教科书作为参考:http://csapp.cs.cmu.edu/)来实现我自己的malloc,但我不确定如何开始。

我有一个方法,malloc_init()使用sbrk返回一块内存。在我的任务范围内,我不允许在此初始呼叫后请求更多内存,并且我允许请求的内存量受MAX_HEAP_SIZE限制(由其他人设置) )。我想我将保留一个指针数组,每个指针都指向一个预定大小的空闲列表。

如何在调用sbrk后设置此数组?我如何计算出每个字节应该包含多少字节" bucket"以及每个freelist的班级大小如何?在代码实现方面,如何设置freelist指针数组?任何提示或提示将不胜感激!我在线查找了代码示例,但没有找到令人满意的代码。

2 个答案:

答案 0 :(得分:3)

不确定是否有"标准"这样做的方法,但只是逻辑思考:你有一大堆内存,你想把它雕刻成不同大小的桶。首先,您需要弄清楚您将要支持的铲斗尺寸。我不是系统程序员,所以我无法说出什么是好的"存储桶大小是,但我想它们会处于2的非连续幂(例如,16字节,64字节,512字节等)。

一旦掌握了铲斗尺寸,就需要将内存blob划分为铲斗。最好的方法是在每个块的开头使用一些blob空间作为标题。标题将包含块的大小和一个标记,表明它是否是空闲的。

struct header
{
    unsigned short blkSize;
    unsigned char  free;
};

init函数中,您将分割blob:

void my_init()
{
    // "base" is a pointer to the start of the blob
    void *base = sbrk((intptr_t)MAX_HEAP_SIZE);
    if (!base)
    {
        // something went wrong
        exit(1);
    }

    // carve up the blob into buckets of varying size
    header *hdr = (header*)base;
    for (int i = 0; i < num16Bblocks; i++)
    {
        hdr->blkSize = 16;
        hdr->free    = 1;

        // increment the pointer to the start of the next block's header
        hdr += 16 + sizeof(header);
    }

    // repeat for other sizes
    for (int i = 0; i < num64Bblocks; i++)
    {
        hdr->blkSize = 64;
        hdr->free    = 1;

        // increment the pointer to the start of the next block's header
        hdr += 64 + sizeof(header);
    }

    // etc
}

当用户请求一些内存时,您将遍历blob,直到找到适合的最小存储桶,将其标记为不再空闲并返回指向存储桶开头的指针:

void *my_malloc(size_t allocationSize)
{
    // walk the blocks until we find a free one of the appropriate size
    header *hdr = (header*)base;
    while (hdr <= base + MAX_HEAP_SIZE)
    {
        if (hdr->blkSize >= allocationSize &&
            hdr->free)
        {
            // we found a free block of an appropriate size, so we're going to mark it
            // as not free and return the memory just after the header
            hdr->free = 0;
            return (hdr + sizeof(header));
        }

        // didn't fit or isn't free, go to the next block
        hdr += hdr->blkSize + sizeof(header);
    }

    // did not find any available memory
    return NULL;
}

要释放(回收)某些内存,只需在标题中将其标记为空闲。

void my_free(void *mem)
{
    // back up to the header
    header *hdr = (header*)(mem - sizeof(header));
    // it's free again
    hdr->free = 1;
}

这是一个非常基本的实现,有几个缺点(例如,不处理碎片,不是很动态),但它可能会给你一个很好的跳跃点。

答案 1 :(得分:3)

内存分配理论需要整章或书籍,但这里有一些快速的想法可以帮助你入门。

您可以执行以下操作:

char *blobs[10];

其中blobs [0]指向16个字节的块,blobs [1]指向32个字节的块,blob [2]指向64个字节的块,... upto blobs [9]指向8k块。然后,当您获得最初的块时,请执行以下操作:

bsize = 8192;
idx = 9;
memsize = MAX_HEAP_SIZE;
while (idx >= 0) {
    while (memsize > bsize) {
        /* carve a bsize chunk from your initial block */
        /* and insert it onto a singly-linked headed by listblobs[idx]; */
        /* use the first (sizeof(char *)) bytes of each chunk as a next pointer */
    }
    bsize /= 2;
    idx--;
}

然后,当您需要分配时,找到正确的列表并从中获取一个块。 你需要使用比请求更大的块,所以你有一个 记录块来自哪个列表的位置,以便您可以释放它。

您可能会发现使blobs数组需要超过10个条目,因此您可以处理更大的请求。

如果您想要更复杂,可以在处理请求时进行块分割。 也就是说,如果有人从64KB blob请求33.2K,那么你可能只需要给出34KB并将64K blob中的剩余空间分成16K,8K,4K,2K块以添加到这些空闲列表中。