您的位置:首页 > 其它

内存逻辑地址到物理地址转化

2016-01-08 11:42 155 查看
我们知道,在计算机里,内存分为虚拟内存和物理内存。 数据是存放在物理内存中的,而程序中使用的是虚拟内存并通过虚拟内存地址来访问数据和代码的,那么操作系统是如何 将虚拟内存地址映射成为实际的物理内存的呢?这是我们这篇文章要详细介绍的问题。

以X86的32位系统为例。如下图所示,在目前的32位的系统中,系统的内存虚拟地址范围为4GB。 其中低2GB主要为应用程序使用(Ring3级别),而高2GB为系统内核使用(Ring0级别)。 每一个程序都有属于自己的一个私有2GB虚存空间,而其中的低64KB为NULL地址区域。 从中看出,NULL不单单是0,而是一个大小范围为[0,64KB]这样的一个区域。
而在[0x7fff0000, 0x7fffffff]区域也被定义为非法区域,禁止程序访问, 这样做的目的是禁止处于Ring3级别的应用程序不小心访问了处于Ring 0级别的内核空间。



程序在执行时,传递给CPU的地址是逻辑地址,它由两部分组成,一部分是段选择符(比如cs和ds等段寄存器的值), 另一部分为有效地址(即偏移量,比如eip寄存器的值)。逻辑地址必须经过映射转换变为线性地址, 线性地址再经过一次映射转为物理地址,才能访问真正的物理内存。转化过程如下:



1)首先逻辑地址需要转化为线性地址。

逻辑地址是以"段寄存器:偏移地址"形式存在的。段寄存器是一个16位的寄存器, 其中第0和1位控制着将要访问段的特权级,第2位说明是在GDT还是LDT寻找地址。 高13位作为一个索引值,总共8192个索引。如下图所示,通过段寄存器里的索引,可以从段描述符表里找到段的基址。 然后用基址加上段内的偏移量,就得到了对应的线性地址。



2)接着线性地址再转化为物理地址。

线性地址可以分为三部分:页目录索引,页表索引,和字节偏移索引。如下图所示,通过页目录索引和CR3寄存器指定的页目录基址之和,可以查询到对应的页表基址。再通过页表索引和页表基址之和, 可以得到对应的页框地址,页框地址再加上页内字节偏移,就最终获得了对应的物理地址。



从C源代码经过编译器编译,链接器链接生成可执行文件之后,接下来程序是怎么执行起来的呢?

接下来,操作系统会将可执行文件加载入内存,CPU将从程序的第一个指令开始执行。在理解CPU是如何执行程序之前,先来看看CPU的构造。CPU主要由运算器、控制器、寄存器组和内部总线等构成。 ALU:运算器是计算机中执行各种算术和逻辑运算操作的部件。运算器由算术逻辑单元(ALU,Arithmetic Logical Unit)、累加器、状态寄存器、通用寄存器组等组成。算术逻辑运算单元(ALU)的基本功能为加、减、乘、除四则运算,与、或、非、异或等逻辑操作,以及移位、求补等操作。计算机运行时,运算器的操作和操作种类由控制器决定。运算器处理的数据来自存储器;处理后的结果数据通常送回存储器,或暂时寄存在运算器中。
CU:控制器是计算机的指挥中心,负责决定执行程序的顺序,给出执行指令时机器各部件需要的操作控制命令。由程序计数器、指令寄存器、指令译码器、时序产生器和操作控制器组成,它是发布命令的“决策机构”,即完成协调和指挥整个计算机系统的操作。控制器从内存中取出一条指令,并指出下一条指令在内存中位置,对指令进行译码或测试,并产生相应的操作控制信号,以便启动规定的动作,指挥并控制CPU、内存和输入/输出设备之间数据流动的方向。 寄存器组用于在指令执行过后存放操作数和中间数据,由运算器完成指令所规定的运算及操作。

1)系统总线

CPU的系统总线包括控制总线,数据总线,地址总线。

数据总线用于传送数据信息。数据总线是双向总线,即它既可以把CPU的数据传送到存储器或I/O接口等其他部件,也可以将其他部件的数据传送到CPU。 地址总线是专门用来传送地址的,由于地址只能从CPU传向外部存储器或I/O端口,所以地址总线总是单向的,这与数据总线不同。地址总线的位数决定了CPU可直接寻址的内存空间大小,比如8位微机的地址总线为16位,则其最大可寻址空间为216=64KB,16位微型机的地址总线为20位,其可寻址空间为220=1MB。一般来说,若地址总线为n位,则可寻址空间为2n字节。有的系统中,数据总线和地址总线是复用的,即总线在某些时刻出现的信号表示数据而另一些时刻表示地址,而有的系统则是分开的。
控制总线用来传送控制信号。控制信号中,有的是微处理器送往存储器和I/O接口电路的,如读/写,中断响应信号等; 也有是其他部件反馈给CPU的,比如:中断申请、复位、总线请求、设备就绪等。因此,控制总线的传送方向由具体控制信号而定, 一般是双向的,控制总线的位数要根据系统的实际控制需要而定。实际上控制总线的具体情况主要取决于CPU。

2)寄存器

CPU的一个重要组成部分就是它的寄存器。 计算机体系结构中常用到的寄存器包括以下几类寄存器(以32位X86系统为例):

a) 通用寄存器:EAX,EBX,ECX,EDX

b) 源变址目标变址寄存器:ESI,EDI

c) 栈相关寄存器:SS,ESP,EBP

d) 代码段寄存器,程序指令寄存器:CS,IP

e) 数据段寄存器:DS(常与ESI寄存器结合使用)

f) 附加段寄存器:ES(常与EDI寄存器集合使用)

g) Flag标志寄存器:

ZF 零标志,零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0;

AF 辅助进位标志,运算过程中第三位有进位值,置AF=1,否则,AF=0;

PF 奇偶标志,当结果操作数中偶数个"1",置PF=1,否则,PF=0;

SF 符号标志,当结果为负时,SF=1;否则,SF=0。溢出时情形例外;

CF 进位标志,最高有效位产生进位值,例如,执行加法指令时,MSB(最高位)有进位,置CF=1;否则,CF=0;

OF 溢出标志,若操作数结果超出了机器能表示的范围,则产生溢出,置OF=1,否则,OF=0。

在64位系统中,寄存器的表示方法为:

通用寄存器:rax, rbx, rcx, rdx

栈寄存器:rsp, rbp

传递参数的寄存器:rdi, rsi, (rdx, rcx,) r8, r9(arguments)

Scratch寄存器:(rbx,) r12, r13, r14, r15(scratch),即可以随时改写的寄存器

那么,CPU是如何一条条执行程序的指令的呢?如下面CPU执行指令图所示, 首先,CPU中的CS寄存器指向了程序被加载内存之后所在代码段的基址,而IP寄存器指向了下一条程序要执行的指令。 CS中的段基址加上IP寄存器中的值,形成一个线性地址,这个线性地址经过转换,形成物理地址,然后通过地址总线, 在对应的内存地址获得对应的一条指令,再把对应的指令通过数据总线传输到CPU的指令缓冲器中,
然后由指令缓冲器传给指令执行控制器,执行对应的指令。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: