认识各种内存地址

什么是物理地址?

物理地址就是内存单元的绝对地址,物理地址0x0000就表示内存条的第一个存储单元,0x0010(16进制)就表示内存条的第17个存储单元,一个存储单元是1byte(8bit)。

你问为什么是1byte?

mem


一个内存条是由若干个黑色的内存颗粒构成的。每一个内存颗粒叫做一个chip。

bank


每个chip中又叠了若干bank

row


在每个bank内部,就是电容的行列矩阵结构了,每一个元素有8个小电容,存储8个bit,也就是一个字节。

什么是线性地址和虚拟地址?

在80286系列以前,CPU只支持实模式操作模式。16位寄存器想要对20位地址线进行寻址,使用分段机制,段基址(16位) x 16(左移4位) + 段内偏移地址(4位)就是物理地址了。
这样的好处是所见即所得,程序员指定的地址就是物理地址,物理地址对程序员是可见的。同时也带来了一些问题:
1) 无法支持多任务。
2) 程序的安全性无法得到保证。
(根本原因就是一个程序直接修改了其他程序的内存,导致崩溃)

80286系列则是被设计来解决这些问题,段式访存得到的改进,原来段基址+段内偏移得到的地址不再是实际的物理地址,而是被称作为线性地址,要经过一个转换层转换才变成一个物理地址。这种CPU操作模式就被称为保护模式了。保护的是:分清楚各个程序使用的存储区域,不允许随便跨界访问。

80286系列之后就进入32位CPU时代了,32位寄存器可以直接访问32位地址总线。但是在保护模式下,地址仍然采用“段地址:偏移地址”的方式来表示。
段值仍然由原来的16位的cs、ds等寄存器表示,但是此时它们仅仅是一个索引,这些个索引指向一个数据结构的表项,表项中详细定义了一个段的起始地址、界限、属性等内容,这个数据结构,叫做GDT(其实还可能是LDT),GDT中的每一个表项,叫做描述符。
这里我们就详细看一下保护模式的寻址方式吧。

protect


1) 寻址时,先找到gdtr寄存器,从中得到GDT的基址。
2) 有了GDT的基址,又有段寄存器中保存的索引,可以得到段寄存器“所指”的那个表项,即所指的那个描述符。
3) 得到了描述符,就可以从描述符中得到该描述符所描述的那个段的起始地址。
4) 有了段的起始地址,将偏移地址拿过来与之相加,便能得到最后的线性地址。
5) 有了线性地址,经过变换,即可得到相应的物理地址。

保护模式虽然解决了内存不被跨界访问,但是其也带来了新的问题,那就是内存碎片。
首先我们了解一下内存碎片为何产生:
首先假设我们有10B内存:

ID 首地址 尾地址 长度 状态
0   0   9   10   空闲  

当程序申请一个长度为3的内存空间后:

ID 首地址 尾地址 长度 状态
0   0   2   3    
1   3   9   7   空闲  

当程序再申请一个长度为2,以及长度为4的内存空间后:

ID 首地址 尾地址 长度 状态
0   0   2   3    
1   3   4   2    
2   5   8   4    
3   9   9   1   空闲  

此时,只剩1个可用空间。如果这时程序再来申请长度大于1的空间,就申请不了,也就是内存不够。
现在,释放掉ID=1的空间:

ID 首地址 尾地址 长度 状态
0   0   2   3    
1   3   4   2   空闲  
2   5   8   4    
3   9   9   1   空闲  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyygfg.html