首页 > 代码库 > 内存的段式管理和页式管理,逻辑地址-虚拟地址-物理地址
内存的段式管理和页式管理,逻辑地址-虚拟地址-物理地址
windowsx86内存管理
1.物理地址(physical address)
用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。
——这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样。所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一对应,也是可以接受的。也许错误的理解更利于形而上的抽像。
2.逻辑地址(logical address)
Intel为了兼容,将远古时代的段式内存管理方式保留了下来。逻辑地址指的是机器语言指令中,用来指定一个操作数或者是一条指令的地址。以上例,我们说的连接器为A分配的0x08111111这个地址就是逻辑地址。
——不过不好意思,这样说,好像又违背了Intel中段式管理中,对逻辑地址要求,“一个逻辑地址,是由一个段标识符加上一个指定段内相对地址的偏移量,表示为 [段标识符:段内偏移量],也就是说,上例中那个0x08111111,应该表示为[A的代码段标识符: 0x08111111],这样,才完整一些”
上面的图我们可以看出在链接的时候进行了重定位
国内操作系统书上都说重定位是逻辑地址到物理地址,但csapp上的重定位是目标文件的符号的相对地址到可执行文件的符号的绝对地址。这个绝对地址才是国内教材口中的逻辑地址。因此,国内教材认为重定位在装入时执行,而csapp和维基百科认为重定位在链接时进行。ps:上面说的重定位都是指静态重定位:-)其实也可以这样理解,这俩个重定位指的是不同的来个重定位。一个是重定位目标文件,另一个是重定位内存地址。
3.虚拟内存(virtual memory)(线性地址)(虚拟地址)
这是对整个内存(不要与机器上插那条对上号)的抽像描述。它是相对于物理内存来讲的,可以直接理解成“不直实的”,“假的”内存,例如,一个0x08000000内存地址,它并不对就物理地址上那个大数组中0x08000000 - 1那个地址元素;
之所以是这样,是因为现代操作系统都提供了一种内存管理的抽像,即虚拟内存(virtual memory)。进程使用虚拟内存中的地址,由操作系统协助相关硬件,把它“转换”成真正的物理地址。这个“转换”,是所有问题讨论的关键。
有了这样的抽像,一个程序,就可以使用比真实物理地址大得多的地址空间。(拆东墙,补西墙,银行也是这样子做的),甚至多个进程可以使用相同的地址。不奇怪,因为转换后的物理地址并非相同的。
——可以把连接后的程序反编译看一下,发现连接器已经为程序分配了一个地址,例如,要调用某个函数A,代码不是call A,而是call 0x0811111111 ,也就是说,函数A的地址已经被定下来了。没有这样的“转换”,没有虚拟地址的概念,这样做是根本行不通的。
打住了,这个问题再说下去,就收不住了。
那我们的问题基本就确定了:这三者是如何转换的。也就是我们最初程序中的逻辑地址是如何转换为线性地址进而转换为物理地址的?
cpu将一个逻辑地址转换为物理地址需要俩步:首先cpu利用段式内存管理单元,将逻辑地址转换成线性地址 ,再利用页式内存管理单元,把线性地址最终转换为物理地址。也就是由最初的代码里的地址转为cpu实际可以用的地址
1.段式管理
我们很早就知道了,就是我们学习8086中地址合成我们就用到了段式管理了。当然16位cpu的8086之所以使用段式管理是因为他的寄存器是16位但是他的地址线是20位的。所以用段式管理。但是在32位下又是什么情况那?32位系统分为三种模式,其中实模式下也就是dos模式,他和16位管理方式一样,
但是在保护模式的时候就不一样了在保护模式下以前的段寄存器不再存储段的基地址而是存储了段选择器的地址,换句话说现在的段选择器就是一个指针,指向了段。获取段中的值在加上偏移地址就可以合成一个线性地址。这个线性地址是32的,理论最大4个G;也就是虚拟内存
注意逻辑地址和线性地址(虚拟地址)的区别:逻辑地址是汇编代码中的地址,而虚拟地址是模拟实际内存的4G地址。逻辑地址+偏移地址=线性地址换;这个过程是段式管理。
2页式管理
对于线性地址我们按照一定大小划分为一个页,为什么要划分页那?源于管理效率。而物理地址往往也划分成页和虚拟页相互对应,叫做页或者页框。换句话说就是对线性地址又划分为一些小格子。而通过页式管理就可以实现线性地址转换物理地址。而且通过计算可以覆盖物理地址的4G当然这个过程也是很复杂的,可以看下面的图
而这么麻烦的一个过程是依靠谁那?是依靠cpu上的MMU。
LINUX内存管理
linux内存管理是没有段管理的,这是因为它的段地址的基地址都是0,都是依靠偏移地址实现4g的虚拟地址的转变。
进而依靠页式管理。
内存的段式管理和页式管理,逻辑地址-虚拟地址-物理地址