一、内存地址:
注意区分三种地址:
1、逻辑地址:
包含在机器语言指令中用来指定一个操作数或一条指令的地址叫做逻辑地址。一个逻辑地址包含一个段和一个偏移量,偏移量指明了从段开始的地方到实际地址之间的距离。
2、线性地址:
是一个32位的无符号整数,可以表示4GB的地址。线性地址通常使用十六进制数字表示,值的范围为0X00000000到0XFFFFFFFF。
3、物理地址:
用于芯片级内存单元寻址,与从微处理器的地址引脚发送到内存总线上的电信号相对应。
4、内存控制单元(MMU):
内存控制单元是将逻辑地址转换为物理地址的硬件电路,其转换过程分为两步:
a、通过分段单元的硬件电路将逻辑地址转换成线性地址;
b、通过分页单元的硬件电路将线性地址转换成物理地址。
二、硬件中的分段:
1、段选择符和段寄存器:
一个逻辑地址包含一个段标识符和一个指定段内相对地址的偏移量。段标识符是一个16位长的字段,称之为段选择符。
段寄存器的唯一目的就是存放段选择符。
段寄存器有6个,分别为cs、ss、ds、es、fs和gs。其中有3个有专门的用处,分别为:
cs
:代码段寄存器,指向包含程序指令的段;
ss
:栈段寄存器,指向包含当前程序栈的段;
ds
:数据段寄存器,指向包含静态数据或者全局数据段;
其他3个段寄存器作一般用途,可以指向任意的数据段。
2、段描述符:
每个段由一个8字节的段描述符表示,它描述了段的特征。段描述符存放在全局描述符表(GDT)或局部描述符表(LDT)中。全局描述符表(GDT)在主存中的地址和大小存放在gdtr控制寄存器中,当前正在被使用的局部描述符表(LDT)地址和大小放在ldtr控制寄存器中。
3、分段单元:
分段单元将逻辑地址转换成为相应的线性地址,其转换过程如下:
a、先检查段选择符的TI字段,以决定段描述符保存在哪一个描述符表中;
b、从段选择符的index字段计算段描述符的地址,index字段的值乘以8(一个字段描述符的大小),这个结果与gdtr或ldtr寄存器中的内容相加;
c、把逻辑地址的偏移量与段描述符Base字段的值相加就得到了线性地址。
三、Linux中的分段:
- 在Linux中,分段可以给每一个进程分配不同的线性空间,而分页可以把同一线性地址空间映射到不同的物理空间。
- 运行在用户态的所有Linux进程都使用一对相同的段来对指令和数据寻址,它们称为用户代码段和用户数据段;运行在内核态的所有Linux进程都使用一对相同的段对指令和数据寻址,它们称为内核代码段和内核数据段。
四、硬件中的分页:
分页单元把线性地址转换成为物理地址。其关键任务是把所请求的访问类型与线性地址的访问权限进行比较,如果这次内存访问是无效的,就产生一个缺页异常。
页
:将线性地址分成以固定长度为单位的组,就称为页。
分页单元将所有的RAM分成固定长度的页框(物理页)。
每个页框包含一个页,即页框长度与页的长度一致。
页表
:把线性地址映射到物理地址的数据结构称之为页表,页表存放在主存中,并在启用分页单元之前必须由内核对页表进行适当的初始化。