【问题标题】:Understanding and implementing malloc理解和实现malloc
【发布时间】:2015-11-30 01:38:48
【问题描述】:

malloc 是如何在内部实现的?如何在以下必要条件下实现malloc

• Malloc 至少分配请求的字节数

• malloc 返回的指针指向一个分配的空间(即程序可以成功读写的空间;)

• 没有其他对 malloc 的调用将分配此空间或其任何部分,除非该指针之前已被释放。

• malloc 应该易于处理:malloc 必须尽快终止(它不应该是 NP 难的!;)

• Malloc 还应提供大小调整和释放功能。

函数遵循以下签名: void * malloc(size_t size);

【问题讨论】:

  • 你能提供降级的理由吗?还是更好的其他详细介绍该主题的SO线程?
  • 我不在其中,但我认为您的问题没有显示任何研究工作。这就是为什么。
  • @HuStmpHrrr :我已经浏览了以下链接和提供的每个答案 - 也只是因为我没有通过所以我一直在寻找更好的答案并通过该教程找到了一个,所以想与社区分享 - 相关 SO 链接 stackoverflow.com/questions/3479330/…
  • 而且我很确定投反对票的人并没有努力阅读我发布的教程 - 如果他努力的话,他会在投反对票前至少花 10 分钟 -
  • 有这样的人。我已经习惯了。

标签: c malloc realloc


【解决方案1】:

解决方案: 为了编写malloc,我们需要知道堆的开始位置和中断位置, 当然,我们需要能够移动休息时间。我们将使用 sbrk() 系统调用来实现这一点。

Sbrk (n) 按给定的增量 n(以字节为单位)移动中断。

sbrk的特殊情况:当increment为null时(即sbrk(0)),返回值为实际的break地址(前一个break地址和新的break地址相同),因此sbrk用于取回作为break的初始位置的堆

步骤 -1 实施(不满足所有条件)

但是在满足高级目标的情况下,它将按请求的大小移动断点,并且用户将在堆上获得内存分配,但不满足执行 realloc 并允许其释放的标准 1)所以我们需要知道每个部分的开始位置以及我们在下一个部分地址的开始位置。 2)那部分的大小是多少 3) 该部分是否免费

所以基本上我们需要一个包含以下内容的列表

免费使用 int 似乎是个坏主意,但由于结构默认对齐,所以没关系。

我们必须注意的另一个条件是 malloc 必须返回对齐的地址。如上所示,元部分已经对齐,我们只需要确保数据部分也是如此。

寻找一个块 Base 是指向堆起始点的全局指针

Extending Heap – 很简单,我们只需移动断点。

现在我们可以执行我们的 malloc 函数,它只是所有经过的小块的包装

【讨论】:

  • 这些图片来自哪本书/网站/教程?
  • 我找到了。这个PDF 有完整的教程,他从那里得到图像。
  • 我昨天已经保留了它-但有人指出外部链接可能会中断-所以我刚刚从教程中发布了sn-p-以下答案供您参考
【解决方案2】:

brk() 和 sbrk()

来自brk()的manual(2)。

brk() 和 sbrk() 改变了程序中断的位置,它定义了进程数据段的结束(即,程序中断是未初始化数据段结束后的第一个位置)。增加program break有给进程分配内存的效果;减少中断会释放内存。

brk() 将数据段的末尾设置为 addr 指定的值,当该值合理时,系统有足够的内存,并且进程不超过其最大数据大小(请参阅 setrlimit(2))。

sbrk() 以递增字节递增程序的数据空间。打电话 增量为0的sbrk()可用于查找当前位置 程序中断。

我会使用它,因为老实说,我无法更好地定义这些函数。请记住,brk() 和 sbrk() 都是由Linux Kernel 提供的system calls。这是它们与 ma​​lloc() 系列之间的第一个主要区别 - ma​​lloc() 和兄弟 是 GLibC 实现。

这个SO Question 会告诉你他们做了什么以及什么是程序中断,所以我不会在这里复制所有这些。

malloc()、calloc()、free()

如前所述,它们由 GLibC 实现,并通过列表管理系统上的内存块。 简单地说(让我强调 simple 部分),ma​​lloc() 将在该列表中找到一个符合请求大小的空闲块用户并返回该块的地址并将其标记为正在使用;另一方面,free() 会将该块返回到列表中。

您可以从here 下载源代码。截至目前,最新的是 2.22。下载后,解压缩并转到 glibc-2.22/malloc。在此目录下,您将找到 malloc (malloc.c) 的源代码。

摘自 malloc.c 文件的第一个注释部分:

算法的主要属性是:

  • 对于大型(>= 512 字节)请求,它是一个纯粹的最佳分配器, 与通常通过 FIFO 决定的关系(即最近最少使用)。

  • 对于小的(默认

  • 介于两者之间,对于大小请求的组合,它确实 尽最大努力同时实现这两个目标。

  • 对于非常大的请求(默认>= 128KB),它依赖于系统 内存映射工具(如果支持)。

有关更长但稍微过时的高级描述,请参阅 this.

我建议点击最后一个链接并阅读它。

此外,这个 PDF file 解释了 ma​​lloc() 和 free() 的内部工作原理。

【讨论】:

  • 不是brk 和sbrk(两者都几乎过时且线程不友好)但mmap(2)
  • @Enzo Ferber :我不认为上面的答案能很好地解释新手的 malloc 实现。
  • 问题是他们是如何完成的 - 如果有人想知道..你的答案没有解决任何这些问题,而是继续谈论 sbrk,我认为这本身可能是不同的话题
  • @oneday 我告诉过你 brk 和 sbrk 是做什么的,这样你就会理解 malloc 背后的概念。然后我给了你实现 malloc 的源代码和它的高级解释。正如 Basile 在上述评论中所说,还有我没有提到的 mmap。另外,在讨论内存分配器的实现时,我不明白为什么 sbrk 会跑题。对于新手程序员,我确实尝试保持简短和简单,因为它已恢复并包含多个链接而不是冗长的解释 - 所以你会先了解整体想法然后深入了解它。
  • @BasileStarynkevitch - 创建内存映射时,内核虚拟内存管理器也必须是单线程的。毕竟,您不能让同一进程中的两个线程以重叠的虚拟映射到不同的物理 RAM 块而告终。所以mmap() 只是将线程瓶颈推低了。
【解决方案3】:

我经历了多个 SO 答案,我相信下面的教程提供了所有四个功能的深入和分步实现..

http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf

【讨论】:

  • 所以答案应该在这里包含最重要的信息。您可以使用链接来提供额外的支持信息,但我们希望我们的网站大部分是独立的,而不是永远依赖远程网站。
  • @Barmar - 很公平 - 我明白你的意思。我最初想发布解决方案并添加学分,但后来我不确定。但我确实明白你的意思
  • @Barmar : 我已经把教程中的 sn-p - 所以它不依赖于外部链接
  • 我想知道为什么你觉得有必要将 sn-p 放在不同的答案中,而不是仅仅编辑这个答案。
  • “错误 404 - 找不到页面”。
猜你喜欢
  • 2016-09-29
  • 1970-01-01
  • 2020-12-15
  • 2013-06-07
  • 2016-10-31
  • 2011-07-22
  • 2014-11-06
  • 2011-07-04
  • 2011-01-17
相关资源
最近更新 更多