linux中逻辑地址与虚拟地址,逻辑地址,虚拟地址,物理地址--深入理解linux内核...

先简单说明一下逻辑地址,虚拟地址,物理地址这三个地址的理解,然后再举个例子,结合实际运行程序的时候深入理解地址概念。

1.逻辑地址:

概念上的地址。通常在机器语言指令中来指定操作数或者指令的地址。(补充:机器语言就是计算机能够直接识别和执行的指令,即二进制形式)。

每一个逻辑地址,包括段地址segment和段内偏移量offset,即逻辑地址=【16位的段标识:20位的偏移offset】

MS-DOS或windows把不同的程序划分为独立的逻辑段。逻辑地址在80*86分段结构中表现得很具体。

为什么会有逻辑地址这个概念?逻辑地址可以理解为分段结构意义上的地址。因为windows或者早起的intel为了让每个程序都只有自己的独立空间,所以就将每个程序作为一个单独的逻辑单元,也就是分段单元。在这个逻辑单元内的意义上的地址就是逻辑地址了。

2.虚拟地址(线性地址):

32位的无符号整数,地址范围:0x00000000 到0xffffffff。

在二级页表结构中,虚拟地址=【10位的页目录:10位的页表:12位的偏移量】

在一级页表结构中,虚拟地址=【1位的页表:22位的偏移量】

为什么会有虚拟地址?虚拟地址其实就是分页结构对应的地址。因为linux kernel将内存划分为大小相等的页,方便内存管理和分配。在分段结构中,每个段的大小不一定相等,不便于管理和分配。

3. 物理地址:

实际存在的地址,用于内存芯片级的内存单位寻址。它们与微处理器的地址引脚发送到内存总线上的电信号相对应。

物理地址由32位或者36位无符号整数表示。(硬件上地址总线为36位,高四位和低32位)。

4. 逻辑地址转换为线性地址:

(1)逻辑地址=[16位的段标识:32位offset]

(2)段标识存储在段寄存器中,段标识=[13位index,1位flag,2位的cpu level].若flag=1,表示段描述符存储在GDT,否则在LDT。

(3)如果段描述符存储在GDT中,则从GDT控制器读取出GDT(全局描述表)的首地址。GDT每个元素是8字节的段描述符,因此,可计算出段标识指向的段描述符地址为:GDT首地址+8*13位的index.  如果在LDT中,计算过程同理。

(4)计算出段标识指向的段描述符地址后,内核将该段描述符从内存读取出来,存放在CPU控制的寄存器中。

(5)段描述符位8个字节大小,存放了段的属性,包括基地址,段长度,等等。

(6)那么,虚拟地址=基地址+32位的offset.

整个转换过程,是由一个硬件电路计算的,效率很高。相当于由段标识映射到段描述符,段描述符中有该段的基地址,基地址+offset就是虚拟地址了。

5.线性地址转换为物理地址:

对于一级页表结构来说, 地址计算过程如下:

(1)页表在内存中的地址存储在cr3寄存器中,我们标记为页表的物理地址;

(2)线性地址的高10位为页目录索引。 页目录的每一项存储了该页的物理地址。所以页的物理地址=(页表的物理地址 + 页目录索引)所指向的页的物理地址。

(3)页的物理地址+偏移量offset 就是该线性地址对应的物理地址。

51252bf709562c483b3dbb6a3c0dd786.png

6.小结:

用户程序经过编译连接后生成由机器语言组成的可执行程序,该可执行程序中的地址是逻辑上的逻辑地址。

当CPU执行可执行程序的指令时,会由一个硬件电路将逻辑地址转换为虚拟地址,再经过一个硬件电路将虚拟地址转换为物理地址。然后CPU就直接从该物理地址指向的内存单元去读数据。

为什么先要转换为虚拟地址呢?是因为逻辑地址是段结构意义上的地址,而内存会被划分为页结构。也就是说,操作系统展现出来的地址是由页地址和页内偏移量组成,而这个就是虚拟地址。至于这个页结构上的虚拟地址如何转换为物理地址,是有硬件电路去计算的。内核不用去管。

因此,可以这样理解, 操作系统把硬件上的物理地址屏蔽掉,抽象出虚拟地址。这样对于程序来说,处于内核层面上的虚拟地址空间,程序不用管内存的物理地址是否够用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值