125

我四处搜索,发现大多数人都提倡使用kmalloc,因为您可以保证获得连续的物理内存块。但是,如果找不到您想要kmalloc的连续物理块,似乎也会失败。
拥有连续的内存块有什么好处?具体来说,为什么我需要在系统调用中有一个连续的物理内存块?有什么理由我不能使用吗? 最后,如果我要在处理系统调用期间分配内存,我应该指定吗?系统调用是否在原子上下文中执行?vmalloc
GFP_ATOMIC

GFP_ATOMIC
分配是高优先级的,不休眠。这是在中断处理程序、下半部分和其他无法睡眠的情况下使用的标志。

GFP_KERNEL 这是正常分配,可能会阻塞。这是在可以安全睡眠时在进程上下文代码中使用的标志。

4

8 回答 8

106

如果缓冲区将由物理寻址总线(如 PCI)上的 DMA 设备访问,您只需要担心使用物理上连续的内存。问题是许多系统调用无法知道它们的缓冲区是否最终会被传递给 DMA 设备:一旦你将缓冲区传递给另一个内核子系统,你真的不知道它要去哪里。即使内核今天不使用缓冲区进行 DMA,未来的开发也可能会这样做。

vmalloc 通常比 kmalloc 慢,因为它可能必须将缓冲区空间重新映射到几乎连续的范围内。kmalloc 从不重新映射,但如果不使用 GFP_ATOMIC 调用 kmalloc 可能会阻塞。

kmalloc 可以提供的缓冲区大小受到限制:128 KBytes *)。如果您需要一个非常大的缓冲区,则必须使用 vmalloc 或其他一些机制,例如在启动时保留高内存。

*) 这适用于早期的内核。在最近的内核上(我在 2.6.33.2 上测试过),单个 kmalloc 的最大大小为 4 MB!(我为此写了一篇相当详细的帖子。) — kaiwan

对于不需要将 GFP_ATOMIC 传递给 kmalloc() 的系统调用,可以使用 GFP_KERNEL。您不是中断处理程序:应用程序代码通过陷阱进入内核上下文,它不是中断。

于 2008-09-22T18:05:22.613 回答
18

简短的回答:下载Linux 设备驱动程序并阅读有关内存管理的章节。

说真的,您需要了解与内核内存管理相关的许多微妙问题——我花了很多时间调试它。

vmalloc() 很少使用,因为内核很少使用虚拟内存。kmalloc() 是通常使用的,但是您必须知道不同标志的后果是什么,并且您需要一种策略来处理失败时会发生什么 - 特别是如果您在中断处理程序中,就像您建议的那样。

于 2008-09-22T18:05:11.383 回答
16

Robert Love 的 Linux Kernel Development(第 12 章,第 3 版第 244 页)非常清楚地回答了这个问题。

是的,在许多情况下不需要物理上连续的内存。在内核中使用 kmalloc 多于 vmalloc 的主要原因是性能。该书解释说,当使用 vmalloc 分配大内存块时,内核必须将物理上不连续的块(页)映射到单个连续的虚拟内存区域。由于内存实际上是连续的并且物理上是不连续的,因此必须将几个虚拟到物理地址的映射添加到页表中。在最坏的情况下,将有(缓冲区大小/页面大小)数量的映射添加到页表中。

这也增加了访问此缓冲区时 TLB(存储最近的虚拟地址到物理地址映射的缓存条目)的压力。这会导致颠簸

于 2012-07-11T22:37:55.803 回答
14

kmalloc()&函数是一个简单的vmalloc()接口,用于以字节大小的块获取内核内存。

  1. kmalloc()函数保证页面在物理上是连续的(并且实际上是连续的)。

  2. vmalloc()函数的工作方式与 类似kmalloc(),但它分配的内存仅是虚拟连续的,不一定是物理连续的。

于 2015-11-30T10:38:44.197 回答
4

拥有连续的内存块有什么好处?具体来说,为什么我需要在系统调用中有一个连续的物理内存块?有什么理由我不能只使用vmalloc吗?

来自谷歌的“我感觉很幸运” vmalloc

kmalloc 是首选方式,只要您不需要很大的区域。问题是,如果你想从/到某些硬件设备进行 DMA,你需要使用 kmalloc,而且你可能需要更大的块。解决方案是在内存碎片化之前尽快分配内存。

于 2008-09-22T17:48:13.280 回答
2

在 32 位系统上,kmalloc() 返回内核逻辑地址(尽管它是一个虚拟地址),它具有到物理地址的直接映射(实际上具有恒定偏移量)。这种直接映射确保我们获得连续的物理 RAM 块。适用于 DMA,我们只给出初始指针并期望之后为我们的操作提供一个连续的物理映射。

vmalloc() returns the kernel virtual address which in turn might not be having a contiguous mapping on physical RAM. Useful for large memory allocation and in cases where we don't care about that the memory allocated to our process is continuous also in Physical RAM.

于 2017-11-05T20:13:31.137 回答
1

其他区别之一是 kmalloc 将返回逻辑地址(否则您指定 GPF_HIGHMEM)。逻辑地址被放置在“低内存”中(在物理内存的第一个千兆字节中)并直接映射到物理地址(使用 __pa 宏进行转换)。此属性意味着 kmalloced 内存是连续内存。

另一方面,Vmalloc 能够从“高端内存”返回虚拟地址。这些地址不能以直接方式转换为物理地址(您必须使用 virt_to_page 函数)。

于 2012-03-12T06:26:37.300 回答
0

In short, vmalloc and kmalloc both could fix fragmentation. vmalloc use memory mappings to fix external fragmentation; kmalloc use slab to fix internal frgamentation. Fot what it's worth, kmalloc also has many other advantages.

于 2020-10-01T12:53:44.267 回答