逻辑地址、物理地址、虚拟地址

物理地址(physical address)

用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。

虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样。所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一对应,也是可以接受的。也许错误的理解更利于形而上的抽像。

虚拟地址(virtual memory)

这是对整个内存(不要与机器上插那条对上号)的抽像描述。它是相对于物理内存来讲的,可以直接理解成“不直实的”,“假的”内存,例如,一个0x08000000内存地址,它并不对就物理地址上那个大数组中0x08000000 - 1那个地址元素;

之所以是这样,是因为现代操作系统都提供了一种内存管理的抽像,即虚拟内存(virtual memory)。进程使用虚拟内存中的地址,由操作系统协助相关硬件,把它“转换”成真正的物理地址。这个“转换”,是所有问题讨论的关键。

有了这样的抽像,一个程序,就可以使用比真实物理地址大得多的地址空间。甚至多个进程可以使用相同的地址。不奇怪,因为转换后的物理地址并非相同的。

——可以把连接后的程序反编译看一下,发现连接器已经为程序分配了一个地址,例如,要调用某个函数A,代码不是call A,而是call 0x0811111111 ,也就是说,函数A的地址已经被定下来了。没有这样的“转换”,没有虚拟地址的概念,这样做是根本行不通的。

逻辑地址(logical address)

Intel为了兼容,将远古时代的段式内存管理方式保留了下来。逻辑地址指的是机器语言指令中,用来指定一个操作数或者是一条指令的地址。以上例,我们说的连接器为A分配的0x08111111这个地址就是逻辑地址。
——不过不好意思,这样说,好像又违背了Intel中段式管理中,对逻辑地址要求,“一个逻辑地址,是由一个段标识符加上一个指定段内相对地址的偏移量,表示为 [段标识符:段内偏移量],也就是说,上例中那个0x08111111,应该表示为[A的代码段标识符: 0x08111111],这样,才完整一些”

线性地址(linear address)或也叫虚拟地址(virtual address)

跟逻辑地址类似,它也是一个不真实的地址,如果逻辑地址是对应的硬件平台段式管理转换前地址的话,那么线性地址则对应了硬件页式内存的转换前地址。

地址转换

第一步:CPU段式管理中——逻辑地址转线性地址

CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址。

一个逻辑地址由两部份组成,【段标识符:段内偏移量】。

段标识符是由一个16位长的字段组成,称为段选择符。其中前13位是一个索引号。后面3位包含一些硬件细节,如图:
在这里插入图片描述

通过段标识符中的索引号从GDT或者LDT找到该段的段描述符,段描述符中的base字段是段的起始地址

段描述符:Base字段,它描述了一个段的开始位置的线性地址。

一些全局的段描述符,就放在“全局段描述符表(GDT)”中,一些局部的,例如每个进程自己的,就放在所谓的“局部段描述符表(LDT)”中。

GDT在内存中的地址和大小存放在CPU的gdtr控制寄存器中,而LDT则在ldtr寄存器中。

段起始地址+ 段内偏移量 = 线性地址
在这里插入图片描述

首先,给定一个完整的逻辑地址[段选择符:段内偏移地址],

1、看段选择符的T1=0还是1,知道当前要转换是GDT中的段,还是LDT中的段,再根据相应寄存器,得到其地址和大小。我们就有了一个数组了。

2、拿出段选择符中前13位,可以在这个数组中,查找到对应的段描述符,这样,它了Base,即基地址就知道了。

3、把Base + offset,就是要转换的线性地址了。
在这里插入图片描述

第一步:页式管理——线性地址转物理地址

再利用其页式内存管理单元,转换为最终物理地址。

linux假的段式管理

Intel要求两次转换,这样虽说是兼容了,但是却是很冗余,但是这是intel硬件的要求。

其它某些硬件平台,没有二次转换的概念,Linux也需要提供一个高层抽像,来提供一个统一的界面。

所以,Linux的段式管理,事实上只是“哄骗”了一下硬件而已。

按照Intel的本意,全局的用GDT,每个进程自己的用LDT——不过Linux则对所有的进程都使用了相同的段来对指令和数据寻址。即用户数据段,用户代码段,对应的,内核中的是内核数据段和内核代码段。

在Linux下,逻辑地址与线性地址总是一致的,即逻辑地址的偏移量字段的值与线性地址的值总是相同的。

linux页式管理

CPU的页式内存管理单元,负责把一个线性地址,最终翻译为一个物理地址。

线性地址被分为以固定长度为单位的组,称为页(page),例如一个32位的机器,线性地址最大可为4G,可以用4KB为一个页来划分,这页,整个线性地址就被划分为一个tatol_page[2^20]的大数组,共有2的20个次方个页。

另一类“页”,我们称之为物理页,或者是页框、页桢的。是分页单元把所有的物理内存也划分为固定长度的管理单位,它的长度一般与内存页是一一对应的。
在这里插入图片描述

每个进程都有自己的页目录,当进程处于运行态的时候,其页目录地址存放在cr3寄存器中。

每一个32位的线性地址被划分为三部份,【页目录索引(10位):页表索引(10位):页内偏移(12位)】

依据以下步骤进行转换:

从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);

根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。

根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;

将页的起始地址与线性地址中最后12位相加。

目的:

内存节约:如果一级页表中的一个页表条目为空,那么那所指的二级页表就根本不会存在。这表现出一种巨大的潜在节约,因为对于一个典型的程序,4GB虚拟地址空间的大部份都会是未分配的;
在这里插入图片描述

32位,PGD = 10bit,PUD = PMD = 0,table = 10bit,offset = 12bit

64位,PUD和PMD ≠ 0

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
内存管理是指操作系统对计算机内存资源进行有效利用和管理的过程。在内存管理中,存在着物理地址虚拟地址逻辑地址和UNC(统一编号字符集)等概念。 物理地址是指计算机内存中的实际物理位置,它是由计算机硬件直接管理的,用来标志内存中存储单元的位置。通过物理地址操作系统可以直接访问内存中的数据。 虚拟地址是在逻辑地址物理地址之间的中间层,它是由操作系统通过地址映射技术生成的。虚拟地址空间将内存分为若干个虚拟页面,每个虚拟页面与物理页面一一对应。在程序运行时,操作系统根据需要将虚拟页面映射到物理页面,进而实现对内存的访问。 逻辑地址是程序中使用的地址,它是相对地址,相对于程序的起始位置。逻辑地址通常是由编译器或连接器进行生成和管理的,它们会根据程序的需要分配逻辑地址空间,并将逻辑地址映射到虚拟地址物理地址。 UNC(统一编号字符集)是一种用于标识计算机网络资源的命名方式。UNC地址是由多个部分组成的,包括计算机名称、共享资源名称和文件/文件夹路径。UNC地址不直接与内存管理相关,而是用于网络中对计算机资源进行唯一标识和访问。 总之,内存管理是操作系统对计算机内存进行有效利用和管理的过程,其中物理地址虚拟地址逻辑地址和UNC等概念在内存管理中扮演不同的角色,分别用于标志内存中存储单元的位置、实现地址映射和唯一标识计算机网络资源等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闫晟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值