【问题标题】:kmalloc() functionality in linux kernellinux内核中的kmalloc()功能
【发布时间】:2013-12-19 08:16:58
【问题描述】:

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

这是x86架构,32位系统。

【问题讨论】:

  • 如果我理解正确的话,kmalloc 不会从所有内存中分配,而是从内核已经可用的内存中分配,而vmalloc 从虚拟内存中分配内存的方式与用户空间相同应用程序。
  • kmalloc() 通过slab/slub/等从物理上连续的范围分配。物理到虚拟的映射是一对一的。对于vmalloc(),为每一页分配一个MMU/PTE值;物理到虚拟的映射不是连续的。高内存是一个通常与 Intel x86 架构相关的概念。请说明您的查询是否与x86 明确相关; Linux 可以在大约 30 种不同的架构上运行。
  • 架构应该将所有物理内存映射到一个虚拟范围;在最新的 ARM Linux 上,这称为 lowmem。分配给用户进程或vmalloc等的所有内存都与这些物理块别名。宏 virt_to_phys()phys_to_virt() 可以转换此范围内的地址(kmalloc() 或内核代码空间,即 lowmem)。底层 MMU 可能会将此范围分配给 4k 页以外的内容;例如 ARM 上的 1MB 部分。

标签: linux linux-kernel


【解决方案1】:

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

kmalloc 通过调用get_free_pages 分配物理上连续的内存(这是首字母缩写词GFP 的意思)。传递给kmallocGFP_* 标志最终在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 和 non-highmem 页面混合的虚拟内存,您必须通过内核的线性空间查看这些虚拟内存,您必须准备好使用映射函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 2021-07-28
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多