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

posted @   lazycoding  阅读(3272)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示