我尝试使用隔离的免费列表(使用此教科书作为参考:http://csapp.cs.cmu.edu/)来实现我自己的malloc,但我不确定如何开始。
我有一个方法,malloc_init()
使用sbrk
返回一块内存。在我的任务范围内,我不允许在此初始呼叫后请求更多内存,并且我允许请求的内存量受MAX_HEAP_SIZE
限制(由其他人设置) )。我想我将保留一个指针数组,每个指针都指向一个预定大小的空闲列表。
如何在调用sbrk
后设置此数组?我如何计算出每个字节应该包含多少字节" bucket"以及每个freelist的班级大小如何?在代码实现方面,如何设置freelist指针数组?任何提示或提示将不胜感激!我在线查找了代码示例,但没有找到令人满意的代码。
答案 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块以添加到这些空闲列表中。