linux内核中的kmalloc()功能

use*_*106 6 linux linux-kernel

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

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

Kaz*_*Kaz 2

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

kmalloc通过调用分配物理上连续的内存get_free_pages(这就是缩写词的含义GFP)。GFP_*传递给kmalloc最终的标志get_free_pages是页面分配器。

由于 highmem 页面需要特殊处理,因此除非将标志添加GFP_HIGHMEM到请求中,否则您将无法获得它们。

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

无论如何,如果您调用get_free_pages(直接或通过kmalloc)来分配两个或更多页面,它必须找到物理上连续的页面。

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

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

vmalloc原则上与 类似mmap,但要简单得多,因为它不处理多个后端(文件系统中具有mmap虚拟功能的设备),也不处理 mmap 允许的映射合并和拆分等问题。该vmalloc区域由仅对内核可见的虚拟地址的保留范围组成(其基地址依赖于体系结构,并且可以在内核编译时由您调整)。分配器vmalloc划分出这个虚拟空间,并用来自 的页面填充它get_free_pages。这些不需要是连续的,因此可以一次获取一个,并将其连接到分配的虚拟空间中。

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

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

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