1、逻辑地址
线性地址与逻辑地址是intel架构下的内存管理机制。机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。即,逻辑地址-->线性地址-->物理地址。
在机器语言指令中,来说明操作数或指令的地址。在x86架构中,每个逻辑地址包括两部分:段(Segment)和偏移量(Offset)。比如:mov 0x80495b0, %eax中的0x80495b0就是逻辑地址。必须加上隐含的DS 数据段的基地址,才能构成线性地址。也就是说 0x80495b0 是当前任务的DS数据段内的偏移。
2、线性地址(虚拟地址)
ARM架构下没有线性地址与逻辑地址,只有虚拟地址与物理地址。
在x86保护模式下,段的信息(段基线性地址、长度、权限等)即段描述符占8个字节,段信息无法直接存放在段寄存器中(段寄存器只有2字节)。Intel的设计是段描述符集中存放在GDT或LDT中,而段寄存器存放的是段描述符在GDT或LDT内的索引值(index)。
Linux中逻辑地址等于线性地址。为什么这么说呢?因为Linux所有的段(用户代码段、用户数据段、内核代码段、内核数据段)的线性地址都是从 0x00000000 开始,长度4G,这样 线性地址=逻辑地址+ 0x00000000,也就是说逻辑地址等于线性地址了。
3、物理地址
物理地址就是内存单元的绝对地址,用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。比如你有一个4G的内存条插在电脑上,物理地址0x0000就表示内存条的第一个存储单元,0x0010就表示内存条的第17个存储单元,不管CPU内部怎么处理地址,最终访问的都是物理地址。在CPU实模式下“段基址+段内偏移地址”就是物理地址,CPU可以使用此地址直接访问内存。
4、段页机制
x86 CPU中段机制(Segmentation)可以将程序的代码(Code)、数据(Data)、栈(Stack)分开,这样多个程序(或进程)就可以在同一个CPU上运行,而相互不会干扰。
页机制(Paging)用来实现传统的以页面为需求的虚拟内存系统,只有程序需要时,才真正给进程分配物理内存。页机制也可以用来隔离多个任务。
5、逻辑地址转为线性地址
在linux下是如下转换的:
1)使用段选择符中的偏移值 在GDT或LDT中定位相应的段描述符。
2)利用段描述符检验段的方位权限和范围,以便确定该段是可访问的并且偏移量位于段的段界限内。
3)把段的偏移量加到段的基地址上最后形成一个线性地址。
6、线性地址转物理地址
分页的基本原理是把线性地址分成固定长度的单元,称为页(page)。页内部连续的线性地址映射到连续的物理地址中。X86每页为4KB(为简化分析,我们不考虑扩展分页的情况)。为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table),页表存放在内存中。
依据以下步骤进行转换:
1)从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
2)根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。
3)根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;
4)将页的起始地址与线性地址中最后12位相加,得到最终我们想要的物理地址;