内核虚拟地址和内核逻辑地址有什么区别?

31
我不太能够准确区分核心逻辑地址和虚拟地址。在 Linux 设备驱动程序书中,它说所有的逻辑地址都是内核虚拟地址,而虚拟地址没有任何线性映射关系。但从逻辑上来讲,我们何时说逻辑地址和虚拟地址,在哪种情况下使用这两个术语呢?
4个回答

48
Linux内核将大部分属于内核的虚拟地址空间映射到物理内存的第一部分,执行1:1映射并具有偏移量。(32位x86略小于1GB,其他处理器或配置可能不同)。例如,在x86上内核代码的地址0xc00000001被映射到物理地址0x1。
这称为逻辑映射-一种1:1映射(带偏移),允许内核访问机器上的大多数物理内存。
但这还不够-有时在32位机器上有超过1GB的物理内存,有时我们想引用非连续的物理内存块作为连续的内存块以简化事情,有时我们想映射不是RAM的内存映射IO区域。
为此,内核在其虚拟地址空间的顶部保留了一个区域,其中进行“随机”页到页映射。那里的映射不遵循逻辑映射区域的1:1模式。这就是我们所说的虚拟映射。
重要的是要补充说明,在许多平台上(x86是一个例子),逻辑和虚拟映射都使用相同的硬件机制(TLB控制虚拟内存)完成。在许多情况下,“逻辑映射”实际上是使用处理器的虚拟内存设施完成的,因此可能有点令人困惑。因此,区别在于映射的模式:逻辑映射为1:1,虚拟映射为某些随机映射。

嗨,我有一个疑惑:在一个拥有512MB物理内存的系统中,所有512MB都被1:1映射到3GB ~ 3GB + 512MB内核逻辑空间,没有高内存。现在内核想要访问虚拟地址3GB + 0x10000,它直接映射到物理地址0x10000,如果这个物理帧已经被使用(例如由用户进程),会发生什么? - hangyuan
这个逻辑映射是否像其他虚拟地址访问一样通过页表进行转换? - torez233

24

基本上有三种寻址方式,它们分别是:

  1. 逻辑寻址:地址由基址和偏移量组成。这实际上就是段式寻址,其中程序中的地址(或偏移量)总是与段描述符中的基值一起使用。
  2. 线性寻址:也称为虚拟地址。这里的地址是连续的,但物理地址却不是。采用分页机制来实现此类寻址。
  3. 物理寻址:主存储器上的实际地址!

在Linux中,内核内存(在地址空间中)超出了3 GB(从3 GB到4 GB),即0xc000000... 内核使用的地址并非物理地址。为了映射虚拟地址,它使用PAGE_OFFSET。必须注意不涉及任何页面转换,即这些地址在本质上是连续的。然而,这方面存在一定的限制,即在x86上最多只能达到896 MB。超过这个限制后,就需要使用分页进行转换。当您使用vmalloc时,会返回这些地址以访问已分配的内存。

简而言之,当有人在用户空间的上下文中提及虚拟内存时,通常是通过分页来实现的。如果提及内核虚拟内存,则是通过PAGE_OFFSET或vmalloc的地址。

(参考-理解Linux内核-2.6版)

Shash


10

内核逻辑地址是通过正常的CPU内存访问函数可以访问到的映射。在32位系统中,即使使用的物理内存超过4GB,也只存在4GB的内核逻辑地址空间。使用kmalloc可以分配由物理内存支持的逻辑地址空间。

虚拟地址不一定有相应的逻辑地址。您可以使用vmalloc分配物理内存,并返回一个没有对应逻辑地址的虚拟地址(例如在具有PAE的32位系统中)。然后可以使用kmap将逻辑地址分配给该虚拟地址。


2
简单来说,虚拟地址包括“高内存”,它不会对物理地址进行1:1映射。如果你的RAM大小超过了内核地址范围(通常情况下,在X86中为1G/3G,即你的RAM为3G但内核寻址范围为1G),那么从kmap()和vmalloc()返回的地址需要内核建立页面表进行内存映射。由于逻辑地址总是由内核进行内存映射(1:1映射),你不需要显式调用内核API(如set_pte)来为特定页面设置页表项。
因此,虚拟地址并不总是逻辑地址。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接