vmalloc和kmalloc有什么区别?


113

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

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

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



4
该文章声称是胡说八道:“通常32位体系结构具有4KB页面大小,而64位体系结构具有8KB页面大小”。我还没有完全阅读它,但是我不会称其为“好”,甚至不会信任它。
AlexandroSánchez18年

1
注意(半相关):vmalloc使用Kernel 5.2(2019年第二季度)更快
-VonC

Answers:


96

如果缓冲区将由物理寻址总线(如PCI)上的DMA设备访问,则只需担心使用物理上连续的内存。问题在于,许多系统调用无法知道其缓冲区是否最终会传递给DMA设备:将缓冲区传递给另一个内核子系统后,您实际上就无法知道它的去向。即使内核今天不将缓冲区用于DMA 将来的开发也可能会使用。

vmalloc通常比kmalloc慢,因为它可能必须将缓冲区空间重新映射到实际上连续的范围内。kmalloc永远不会重新映射,尽管如果不使用GFP_ATOMIC调用,kmalloc可能会阻塞。

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

*) 早期的内核都是如此。在最近的内核上(我在2.6.33.2上进行了测试),单个kmalloc的最大大小为4 MB!(我对此写了一篇相当详细的文章。)— kaiwan

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


1
我以为系统调用是通过触发int $ 0x80进入的?(即中断)?
FreeMemory

2
int $ 0x80是软件中断,也称为陷阱。中断处理程序的意思是硬件中断,例如当用户按下键或移动动作时。
Branan

系统调用用于用户空间到内核空间的转换... kmalloc仅在内核上下文中使用?
AIB

3
@FreeMemory:int $ 0x80是特定于x86的,因此,它也是被sysenter / syscall(在x86上)取代的旧方法。
约根森

18

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

认真地说,您需要了解许多与内核内存管理相关的细微问题-我花了大量时间调试它的问题。

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


1
“因为内核很少使用虚拟内存”,为什么会这样呢?
Trey

因为您通常不希望内核块在等待内核将内存交换到磁盘存储中或从磁盘存储中交换出来时……
Mike Heinz,

不,使用vmalloc分配的内核内存永远不会交换。仅用户空间内存可以交换。内核地址空间不可交换,并且vmalloc在内核地址空间中分配。
user2679859

13

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

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

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


11

kmalloc()vmalloc()功能是在字节大小的块获得内核存储器的简单接口。

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

  2. vmalloc()函数的工作方式与相似kmalloc(),除了它分配的内存实际上是连续的,而不一定是物理连续的。


4

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

来自Google的“我很幸运” vmalloc

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


看,我读过,对我来说没有意义。我知道在区域使用kmalloc ;但是对于较小的分配,为什么不使用vmalloc避免碎片化物理内存?
FreeMemory

因为您应该信任内核才能做到最好;如果它认为分配单个块更好,那么它将这样做。vmalloc仅用于您绝对必须具有连续块的情况。
Dark Shikari

我想这很有道理,但似乎违反直觉。kmalloc听起来似乎应该在性能最为重要的情况下使用它(即,磁盘IO不能困扰我)。另外,GFP_ATOMIC又如何呢?
FreeMemory

2

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

vmalloc()返回内核虚拟地址,该地址又可能在物理RAM上没有连续的映射。对于大内存分配以及在我们不关心分配给我们的进程的内存在物理RAM中也是连续的情况下很有用。


1

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.