linux内核中的kmalloc()功能

时间:2013-12-03 10:19:17

标签: linux linux-kernel

我确实遇到过使用我们可以从高内存分配的kmalloc的LDD书籍。我这里有一个基本问题。 1)但据我所知,我们无法直接从内核访问高内存(除非它通过kmap()映射到内核空间)。我没有看到为kmalloc()保留任何映射区域,但是对于vmalloc()它是存在的。那么,如果从高内存分配kmalloc()将映射到内核地址的哪一部分?

这是在x86架构上,32位系统。

1 个答案:

答案 0 :(得分:2)

我的知识可能已经过时,但堆栈是这样的:

kmalloc通过调用get_free_pages来分配物理上连续的内存(这是首字母缩略词GFP所代表的)。传递给GFP_*的{​​{1}}标记最终位于kmalloc,即页面分配器。

由于highmem页面需要特殊处理,除非您在请求中添加get_free_pages标志,否则不会获得它们。

Linux中的所有内存都是虚拟的(这种泛化不完全正确,而且取决于体系结构,但让我们继续使用它,直到本段中的下一个带括号的语句)。然而,存在一系列内存,在重新映射页面的意义上不受虚拟化的影响:它只是虚拟地址和物理地址之间的线性映射。 GFP_HIGHMEM分配的内存是线性映射的,高内存除外。 (在某些体系结构中,不使用MMU就支持内存范围的线性映射:它只是逻辑地址到物理的简单算术转换:添加位移。在其他体系结构中,线性映射是使用MMU完成的。)

无论如何,如果你致电get_free_pages(直接或通过get_free_pages)分配两个或更多页面,它必须找到物理连续的页面。

现在,虚拟内存也在kmalloc之上实现,因为我们可以采用这种方式分配页面,并将其安装到虚拟地址空间中。

这就是get_free_pages的工作原理以及用户空间的所有其他功能。当提交虚拟内存(由物理页面,页面错误或其他任何内容支持)时,页面来自mmap。除非该页面是highmem,否则它具有线性映射,以便在内核中可见。此外,它连接到正在进行请求的虚拟地址空间。一些内核数据结构跟踪这一点,当然它被打入页面表中,因此MMU实现了它。

get_free_pages原则上与vmalloc类似,但更简单,因为它不处理多个后端(文件系统中具有mmap虚函数的设备)并且不处理mmap允许的聚合和分割映射等问题。 mmap区域由一系列保留的虚拟地址组成,这些虚拟地址仅对内核可见(其基址与架构有关,可在内核编译时由您调整)。 vmalloc分配器创建了虚拟空间,并使用vmalloc中的页面填充它。这些不需要是连续的,因此可以一次获得一个,并连接到分配的虚拟空间。

Highmem页面是物理内存,在内核表示物理内存的线性映射中无法寻址。存在Highmem是因为内核在物理内存上的线性“窗口”并不总是足以覆盖所有内存。 (例如,假设你有1GB的窗口,但有4GB的RAM。)因此,对于所有内存的覆盖,除了线性地图之外,还有一些较小的“非线性”地图,其中有选择地使页面可见,使用get_free_pageskmap的临时基础。将页面放置到此视图中被视为获取必须谨慎使用并尽快释放的宝贵资源。

highmem页面可以像任何其他页面一样安装到虚拟内存映射中,并且该页面视图不需要特殊的“highmem”处理。任何地图:进程的映射或vmalloc范围。

如果你正在处理一些可能是highmem和非highmem页面混合的虚拟内存,你必须通过内核的线性空间来查看,你必须准备好使用映射函数。