Linux 内核中逻辑地址/虚拟地址/线性地址三者的区别

本博文引自我的知乎回答:Linux 线性地址,逻辑地址和虚拟地址的关系?

为了防止歧义,以下术语都用英文。部分术语不做解释了,不然答案就太长了。

以下讲解都是以代码段为例

在 Intel 平台下,逻辑地址(logical address)是 selector:offset 这种形式,selector 是 CS 寄存器的值,offset 是 EIP 寄存器的值。如果用 selector 去 GDT( 全局描述符表 ) 里拿到 segment base address(段基址) 然后加上 offset(段内偏移),这就得到了 linear address。我们把这个过程称作段式内存管理

如果再把 linear address 切成四段,用前三段分别作为索引去PGD、PMD、Page Table里查表,最终就会得到一个页表项(Page Table Entry),那里面的值就是一页物理内存的起始地址,把它加上 linear address 切分之后第四段的内容(又叫页内偏移)就得到了最终的 physical address。我们把这个过程称作页式内存管理

问题来了,为什么没提到 virtual address,这是个什么东西?其实在 Intel IA-32 手册里并没有提到这个术语,但是在内核的确是用到了这个概念,比如__va和__pa这两个宏定义。看似神秘的 virtual address 究其本质就是程序里面使用的地址比如一个指针值,指针的本质就是 EIP 寄存器里的值,说直白点,virtual address 就是 EIP 寄存器的值。你会发现我们上面说过,logical address 由 selector 和 offset 两部分组成,offset 也是 EIP 寄存器的值,所以结论为:logical address 的 offset 正是 virtual address,它俩是一个东西。

既然搞明白了 logical address 和 virtual address 的关系,那么我们再来看下,linear address 和 virtual address 是什么关系。在上面讲到的段式内存管理中,Linux 内核会将 segment base address(段基址)设成 0,于是就有 linear address = 0+offset,又因为 virtual address 就是 offset,所以算出的 linear address在数值上等于 virtual address,注意,是数值上等于,它们之间是差了段基址的,只不过段基址为 0 罢了。

网上很多资料认为逻辑地址是虚拟地址的别名,其实它们不是一个东西。还有很多资料把线性地址当作虚拟地址的别名,其实它们也不是一个东西,只是Linux在x86下将它们搞得数值相等而已,虽然值相等但是本质不同

---------------------------------我是分割线-------------------------------------------

讲到这里,三者之间的关系就讲明白了,最后说下为什么这三个概念会如此混乱。

按照 Intel 的设计,段式内存管理中的段类型分为三种:代码段(上面讲了)、数据段、系统段(TSS之类的),实在是太麻烦了。我们只靠页式内存管理就已经可以完成Linux内核需要的所有功能,根本不需要段映射,但是段映射这玩意儿又关不掉,那就只能上点手段了。于是,Linux内核将所有类型的段的 segment base address 都设成0,段限长都设成最大(具体数值不展开讲了,涉及到段描述符结构,很麻烦,这里理解成地址总线的最大寻址限度即可),那么这样一来所有段都重合了,也就是不分段了,此外由于段限长是地址总线的寻址限度,所以这也相当于所有段跟整个线性空间重合了。虚拟地址本来是在段内的偏移量,现在段就是整个线性空间,所以虚拟地址就成了在整个线性空间内的偏移量,这和线性地址的概念一样,所以内核开发者都已经将虚拟地址和线性地址当作一个东西了。像是 Understand The Linux Kernel 这本书里面为了避免混淆,除了在开头和术语表中引用了  virtual address 这个词组之外,其他地方全是用的 linear address。

看完这个答案,你会发现我们绕了一圈回来,虽然逻辑地址的概念很清晰,但是虚拟地址和线性地址依然可以不作区分,因为区分了也没什么用,内核里这俩概念是通用的。不过,知道点区别还是不至于在某些时候把自己搞晕,尤其是有些书和教程里面这两个词不说缘由就混着用,这很蛋疼。好了,最后结论就是,这两个概念区分开来的确更加清晰,但如果不作区分而直接把虚拟地址看作线性地址的别名,对你理解内核也不会产生任何影响。

时间: 2024-10-10 13:51:02

Linux 内核中逻辑地址/虚拟地址/线性地址三者的区别的相关文章

linux内存管理---物理地址、线性地址、虚拟地址、逻辑地址之间的转换

linux内存管理---虚拟地址.逻辑地址.线性地址.物理地址的区别(一) 这篇文章中介绍了四个名词的概念,下面针对四个地址的转换进行分析 CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步(如下图): 首先,将给定一个逻辑地址(其实是段内偏移量,这个一定要理解!!!),CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址, 其次,再利用其页式内存管理单元,转换为最终物理地址. 这样做两次转换,的确是非常麻烦而且没有必要的,因为直接可以把线性地址抽像给进程.之所以这样冗余

LINUX 逻辑地址、线性地址、物理地址和虚拟地址 转

一.概念物理地址(physical address)用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应.——这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样.所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一

Linux内存管理--虚拟地址、逻辑地址、线性地址和物理地址的区别(二)【转】

本文转载自:http://blog.csdn.net/yusiguyuan/article/details/9668363 这篇文章中介绍了四个名词的概念,下面针对四个地址的转换进行分析 CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步(如下图): 首先,将给定一个逻辑地址(其实是段内偏移量,这个一定要理解!!!),CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址, 其次,再利用其页式内存管理单元,转换为最终物理地址. 这样做两次转换,的确是非常麻烦而且没有必要的,

[转帖]Linux下逻辑地址、线性地址、物理地址详细总结

Linux下逻辑地址.线性地址.物理地址详细总结 https://www.cnblogs.com/alantu2018/p/9002441.html 总结的挺好的 现在应该是段页式管理 使用MMU和TLB 实现 线性地址 逻辑地址 和物理地址的映射. 一.逻辑地址转线性地址    机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到. 我们写个最简单的hello world程序,用gcc编译,再反编译后会看到以下指令:

X86下逻辑地址、线性地址、虚拟地址和物理地址的理解

参考:http://bbs.chinaunix.net/thread-2083672-1-1.html 本贴涉及的硬件平台是X86,如果是其它平台,不保证能一一对号入座,但是举一反三,我想是完全可行的. 一.概念 物理地址(physical address) 用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应. --这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,

linux内存管理---虚拟地址、逻辑地址、线性地址、物理地址的区别(一)

分析linux内存管理机制,离不了上述几个概念,在介绍上述几个概念之前,先从<深入理解linux内核>这本书中摘抄几段关于上述名词的解释: 一.<深入理解linux内核>的解释 逻辑地址(Logical Address) 包含在机器语言指令中用来指定一个操作数或一条指令的地址(有点深奥).这种寻址方式在80x86著名的分段结构中表现得尤为具体,它促使windows程序员把程序分成若干段.每个逻辑地址都由一个段和偏移量组成,偏移量指明了从段开始的地方到实际地址之间的距离. 线性地址(

linux2.6 内存管理——逻辑地址转换为线性地址(逻辑地址、线性地址、物理地址、虚拟地址)

Linux系统中的物理存储空间和虚拟存储空间的地址范围分别都是从0x00000000到0xFFFFFFFF,共4GB,但物理存储空间与虚拟存储空间布局完全不同.Linux运行在虚拟存储空间,并负责把系统中实际存在的远小于4GB的物理内存根据不同需求映射到整个4GB的虚拟存储空间中.Linux主要工作在保护模式下.80X86从逻辑地址到物理地址变换中经过了两个阶段.第一阶段使用分段机制把程序的逻辑地址变换成处理器可寻址内存空间(称为线性地址空间)中的地址.第二阶段的分页机制把线性地址转换成物理地址

操作系统 内存地址(逻辑地址、线性地址、物理地址)概念

逻辑地址(Logical Address) 是指由程序产生的与段相关的偏移地址部分.例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址,不和绝对物理地址相干.只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换):逻辑也就是在Intel 保护模式下程序执行代码段限长内的偏移地址(假定代码段.数据段如果完全一样).应用程序员仅需与逻辑地址打交道,而分段和分页机制对您来说是

(笔记)Linux内核中内存相关的操作函数

linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) 内核空间申请指定大小的内存区域,返回内核空间虚拟地址.在函数实现中,如果申请的内存空间较大的话,会从buddy系统申请若干内存页面,如果申请的内存空间大小较小的话,会从slab系统中申请内存空间.有关buddy和slab,请参见<linux内核之内存管理.doc> gfp_t flags 的选项