理解和实现malloc
malloc是如何在内部实现的? 如何在以下必要条件下实现malloc
•Malloc至少分配请求的字节数
•malloc返回的指针指向已分配的空间(即程序可以成功读取或写入的空间;)
•除非指针已被释放,否则不会有其他任何对malloc的调用分配此空间或其任何部分。
•malloc应该是可处理的:malloc必须尽快终止(它不应该是NP-hard!;)
•Malloc还应提供调整和释放。
该函数服从以下签名:void * malloc(size_t size);
brk()和sbrk()
来自brk()的手册(2 ) 。
brk()和sbrk()更改程序中断的位置,该中断定义了进程数据段的结尾(即程序中断是未初始化数据段结束后的第一个位置)。 增加程序中断会为进程分配内存; 减少中断释放内存。
brk()将数据段的末尾设置为由addr指定的值,当该值合理时,系统具有足够的内存,并且该进程不超过其最大数据大小(请参阅setrlimit(2) )。
sbrk()通过增量字节递增程序的数据空间。 以增量0调用sbrk()可用于查找程序中断的当前位置。
我会用它,因为,说实话,我无法更好地定义这些功能。 请记住, brk()和sbrk()是Linux内核提供的系统调用。 这是它们和malloc()系列的第一个主要区别 - malloc()和兄弟是GLibC实现。
这个SO问题会告诉你他们究竟做了什么,程序中断是什么,所以我不会在这里复制所有这些。
malloc(),calloc(),free()
如上所述,它们由GLibC实施,并通过列表管理系统上的内存块。 简单地说 (让我强调一下简单的部分), malloc()将在该列表上找到一个适合用户请求大小的空闲块并返回该块的地址并将其标记为正在使用中; 另一方面, free()会将该块返回给列表。
你可以从这里下载源代码。 截至目前,最新的是2.22 。 一旦下载,解压并转到glibc-2.22 / malloc 。 在这个目录下你可以找到malloc(malloc.c)的源代码。
从malloc.c文件的第一个注释部分提取:
算法的主要属性是:
对于大的(> = 512字节)请求,它是一个纯粹的最佳拟合分配器,通常通过FIFO决定关系(即最近最少使用)。
对于小的(默认情况下<64字节)请求,它是一个缓存分配器,用于维护快速回收块的池。
在两者之间,以及对于大型和小型请求的组合,它尽其所能地尝试同时实现两个目标。
对于非常大的请求(默认大于等于128KB),它依赖于系统内存映射功能(如果支持)。
对于较长但稍微过时的高级描述,请参阅此。
我建议遵循最后一个链接并阅读它。
此外,这个解释malloc()和free()的内部工作的PDF文件。
我已经经历了多个SO的答案,我相信下面的教程提供了所有四个功能的深度和一步一步的实施。
http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf
解决方案:为了编写一个malloc,我们需要知道堆的开始位置和中断位置,当然我们需要能够移动中断。 我们将使用sbrk()sys调用来实现这一点。
Sbrk(n)以给定的增量n(以字节为单位)移动中断。
sbrk的特例:当增量为空(即sbrk(0))时,返回的值是实际的中断地址(前面的和新的中断地址是相同的。)sbrk因此用于检索堆的开始是休息的初始位置
步骤-1实施(不满足所有标准)
但是在高级别的目标是满意的,它会按要求的大小移动断点,并且用户会在堆上获得内存分配,而没有满足标准来执行realloc并允许它释放1)因此,我们需要知道每个部分从哪里开始,以及当我们在下一个的每个部分地址的开始处。 2)该部分的大小是多少3)如果该部分是免费的
所以基本上我们需要一个包含以下内容的列表
免费使用int可能看起来不是一个好主意,但由于struct默认对齐,所以不会起作用。
我们必须注意的另一个条件是malloc必须返回对齐的地址。 如上所述,meta部分已经对齐,我们只需确保数据部分也是如此。
查找块基础是指向堆起点的全局指针
扩展堆 - 它很简单,我们只是移动断点。
现在我们可以做我们的malloc函数,它只是所有小块的包装
链接地址: http://www.djcxy.com/p/28481.html上一篇: Understanding and implementing malloc
下一篇: what does casting a pointer 'actually' do under the hood?