物理地址是什么?物理地址是存储器单元的绝对地址,物理地址0x0000表示存储器条的第一个存储器单元,0x0000 (十六进制)表示存储器条的第十七个存储器单元,以及一个存储器单元
为什么是1字节?
一个记忆棒由多个黑色的记忆粒子组成。 内存中的每个粒子都称为chip。
每个chip上重叠了几个银行
每个存储体内部有容量的矩阵矩阵结构,每个元素有8个小容量,存储8个位,即1字节。
什么是线性地址和虚拟地址? 在80286系列之前,CPU只支持实模式操作模式。 16位寄存器试图寻址20位的地址线。 使用分段机制,头发(16位) x 16 (向左移动4位)分段中的偏移地址(4位)是物理地址。
这样做的好处是,程序员指定的地址是物理地址,物理地址看起来像程序员。 出现了一些问题:
1 )无法支持多任务处理。
2 )程序的安全性得不到保证。
(根本原因是一个程序直接修改了另一个程序的内存并崩溃。)
80286系列是为解决这些问题而设计的,改进了分段访问保存。 原本在顺利的头发中偏移得到的地址,不是实际的物理地址,而是叫做线性地址,经过转换层转换后才成为物理地址。 这样的CPU动作模式称为保护模式。 受保护的是明确每个程序使用的存储空间,不允许擅自跨境访问。
80286系列之后,进入32位CPU时代,32位寄存器可以直接访问32位地址总线。 但是,在保护模式下,地址仍然用“段地址:偏移地址”来表示。
段值仍然由原始的16位cs、ds等寄存器来表示,但这种情况下它们只是索引,这些索引指向一个数据结构的显示项目。 在显示项目中详细定义了段的开头地址、边界、属性等内容,该数据结构被称为GDT (实际上为LDT ),GDT的各显示项目被称为描述符。
现在,让我们详细了解一下保护模式的寻址方法。
1 )寻址时,首先找到GDTr寄存器,从中获得gdt的基地址。
2 ) GDT的基地址和段寄存器中存储的索引可以得到段寄存器“指向”的表条目,即指向的描述符。
3 )一旦获得描述符,就可以从描述符获得该描述符所描述段的开头地址。
4 )因为有段的起始地址,所以把偏移地址拿来进行加法运算,就得到了最后的线性地址。
5 )如果有线性地址,通过转换可以得到适当的物理地址。
保护模式解决了防止内存被跨境访问的问题,但也带来了内存碎片的新问题。
首先,让我们看看内存碎片是为什么发生的。
首先,假设有10B的内存。
ID起始地址结束地址长度状态00910空闲程序请求长度为3的存储器区域后:
ID起始地址结束地址长度状态00231397空闲程序重新申请长度2、长度4的存储器区域后:
ID起始地址结束地址长度状态0023134225843991为空闲时,只剩下一个可用空间。 此时,如果再次申请程序大于长度1的空间,则无法申请。 也就是说,内存不足。
现在,释放ID=1的空间。
可知ID起始地址末尾地址长度状态00231342空闲25843991空闲当前可用的存储器区域为3,但这3个空闲区域不是连续的。
因此,如果程序现在申请长度为3的内存区域,同样无法申请,内存将不足。 这叫做内存碎片。
如何解决内存碎片? 于是寻呼机制就形成了。 接下来详细说明一下寻呼吧。
首先,将物理存储器按某个大小均等地分割。 例如,我现在以两个内存单位,分割内存。 也就是说,每两个连续的内存区域组成一个内存页面。
地址页面ID状态00空121空342空563空784在内的钢铁侠之后,系统必须以类似的方式维护内存信息表。 用于ID的存储器页面ID现在程序申请长度为3的存储器空间,但是现在申请的最小单位是页面,一个页面的长度为2,所以现在需要申请两个页面,即四个存储器空间。 看,这浪费了一个内存空间。
地址页面ID状态00121342空闲563空闲784用于向内钢铁侠ID的存储器页面id00,1接下来程序重新申请长度为1、长度为2的空间:
地址页面ID状态00121342563784用于向内的钢铁侠ID的存储器页面ID00、11223释放ID=1、存储器页面ID为2的存储器空间信息:
地址页面ID状态00121342空闲用于面向563784的钢铁侠ID的内存页面id00、123目前共有4个内存区域,但发生了不连续的以前的状况。
但是,由于现在是分页管理机制,所以现在也可以继续申请长度为4的内存区域。
因为没有碎片,所以可以尽量把空间全部用完。 但是仔细想想,这个优点的背后,也需要很多成本。
对于分页方式,程序需要记录内存页面ID,每次使用时都需要将内存页面ID翻译为实际的内存地址,转换次数多一次。
而且,该模式如上所述申请了3个内存区域,实际上分配了2页共计4个内存区域,浪费了1个内存区域等,浪费了一些内存。
还有一点需要注意。 此时,“在顺畅的头发中错开地址”会通过分段部件
处理后得到的线性地址就不再是物理地址了,而是虚拟地址了。从下图我们能够清楚的看出来我们最后的线性地址表示的是页表的地址,而不是物理地址了。
什么是逻辑地址和有效地址?
无论CPU在什么模式下,段内偏移地址又称为有效地址或者逻辑地址(只是叫法不一样罢了),例如实模式下mov ax, [0x7c00],0x7c00就是逻辑地址(或有效地址),但这条指令最终操作的物理地址是DS*16+0x7c00。
Linux最初就是在32位的80386系列上设计的,并且没有使用分段机制,所以在Linux上逻辑地址和线性地址就是一回事了。
一图以概括:
我的博客:https://geanqin.github.io/