【发布时间】:2012-02-01 06:26:09
【问题描述】:
我无法准确区分内核逻辑地址和虚拟地址。在 Linux 设备驱动程序书中,它说所有逻辑地址都是内核虚拟地址,并且虚拟地址没有任何线性映射。但是,当我们说它是合乎逻辑的,当我们说虚拟时,我们在什么情况下使用这两个?
【问题讨论】:
标签: linux-kernel linux-device-driver
我无法准确区分内核逻辑地址和虚拟地址。在 Linux 设备驱动程序书中,它说所有逻辑地址都是内核虚拟地址,并且虚拟地址没有任何线性映射。但是,当我们说它是合乎逻辑的,当我们说虚拟时,我们在什么情况下使用这两个?
【问题讨论】:
标签: linux-kernel linux-device-driver
Linux内核映射属于内核的大部分虚拟地址空间,以物理内存第一部分的偏移量进行1:1映射。 (对于 32 位 x86 而言,1Gb 略低于 1Gb,对于其他处理器或配置可能会有所不同)。例如,对于 x86 上的内核代码,地址 0xc00000001 映射到物理地址 0x1。
这称为逻辑映射 - 一种 1:1 映射(带有偏移),允许内核访问机器的大部分物理内存。
但这还不够 - 有时我们在 32 位机器上拥有超过 1Gb 的物理内存,有时我们想要将非连续物理内存块引用为连续的以使事情变得简单,有时我们想要映射内存映射的 IO 区域,这些区域是不是内存。
为此,内核在其虚拟地址空间的顶部保留一个区域,在该区域中执行“随机”页到页映射。那里的映射不遵循逻辑映射区域的 1:1 模式。这就是我们所说的虚拟映射。
重要的是要补充一点,在许多平台上(x86 就是一个例子),逻辑和虚拟映射都是使用相同的硬件机制(TLB 控制虚拟内存)完成的。在许多情况下,“逻辑映射”实际上是使用处理器的虚拟内存设施完成的,所以这可能有点令人困惑。因此,不同之处在于完成映射的模式:逻辑为 1:1,虚拟为随机。
【讨论】:
寻址方式基本上有3种,分别是
现在,在 linux 中,内核内存(在地址空间中)超过 3 GB(3GB 到 4GB),即 0xc000000..内核使用的地址不是物理地址。为了映射虚拟地址,它使用 PAGE_OFFSET。必须注意不涉及页面翻译。即这些地址本质上是连续的。但是,这有一个限制,即 x86 上的 896 MB。超出哪个分页用于翻译。当你使用vmalloc时,这些地址被返回来访问分配的内存。
简而言之,当有人在用户空间的上下文中引用虚拟内存时,就是通过分页。如果提到内核虚拟内存,则它是 PAGE_OFFSET 或 vmalloced 地址。
(参考 - 了解 Linux 内核 - 基于 2.6 )
沙士
【讨论】:
内核逻辑地址是内核代码通过正常的 CPU 内存访问函数可访问的映射。在 32 位系统上,仅存在 4GB 的内核逻辑地址空间,即使使用的物理内存多于该空间。物理内存支持的逻辑地址空间可以用kmalloc分配。
虚拟地址不一定有对应的逻辑地址。您可以使用vmalloc 分配物理内存并取回没有相应逻辑地址的虚拟地址(例如,在具有 PAE 的 32 位系统上)。然后,您可以使用kmap 为该虚拟地址分配一个逻辑地址。
【讨论】:
简单来说,虚拟地址会包含“高端内存”,它不会对物理地址进行 1:1 映射,如果您的 RAM 大小超过内核的地址范围(通常,对于 1G/3G 在X86,你的内存是3G,但你的内核寻址范围是1G),还有kmap()和vmalloc()返回的地址,这需要内核为内存映射建立页表。由于逻辑地址始终是由内核映射的内存(1:1 映射),因此您不需要显式调用内核 API,例如 set_pte 来为特定页面设置页表条目。
所以虚拟地址不能一直是逻辑地址。
【讨论】: