vmalloc和kmalloc有什么区别?

时间:2008-09-22 17:46:20

标签: c linux-kernel kmalloc vmalloc

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

  

GFP_ATOMIC
  分配是高优先级的   不睡觉这是标志   用于中断处理程序,底部   你和你的一半和其他情况   无法入睡。

     

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

8 个答案:

答案 0 :(得分:85)

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

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

kmalloc的缓冲区大小有限:128 KBytes *)。如果你需要一个非常大的缓冲区,你必须使用vmalloc或其他一些机制,比如在启动时保留高内存。

  

*) 以前的内核都是如此。在最近的内核上(我在2.6.33.2上对此进行了测试),单个kmalloc的最大大小最多为4 MB! (我写了一篇相当detailed post on this。) - kaiwan

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

答案 1 :(得分:16)

简短回答:下载Linux Device Drivers并阅读有关内存管理的章节。

说真的,你需要了解很多与内核内存管理相关的细微问题 - 我花了很多时间来调试它的问题。

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

答案 2 :(得分:12)

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

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

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

答案 3 :(得分:10)

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

  1. kmalloc()函数可确保页面在物理上连续(并且几乎是连续的)。

  2. vmalloc()函数的工作方式与kmalloc()类似,不同之处在于它分配的内存几乎是连续的,不一定是物理上连续的。

答案 4 :(得分:5)

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

来自Google vmalloc上的“我感觉很幸运”:

kmalloc是首选方式,只要您不需要非常大的区域。麻烦的是,如果你想从/向某些硬件设备做DMA,你需要使用kmalloc,你可能需要更大的块。解决方案是尽快分配内存 记忆变得支离破碎。

答案 5 :(得分:2)

在32位系统上,kmalloc()返回内核逻辑地址(虽然它是一个虚拟地址),它具有直接映射(实际上具有常量偏移)到物理地址。 这种直接映射确保我们获得连续的物理RAM块。适合DMA,我们只提供初始指针,并期望在此后进行连续的物理映射。

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

答案 6 :(得分:1)

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

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

答案 7 :(得分:0)

简而言之,vmalloc和kmalloc都可以修复碎片。 vmalloc使用内存映射来修复外部碎片; kmalloc使用slab修复内部碎片。值得一提的是,kmalloc还具有许多其他优点。