从进程说起
每当创建一个进程,就会在内存开辟一片区域,用于存储该进程的代码、数据、进程控制块等所有与该进程相关的信息。这些信息的排列顺序对应逻辑地址,在内存中实际存储的位置对应物理地址,他们都是从零开始编址。
在单道系统中,一次只装入一个进程信息,逻辑地址与物理地址一一对应;但是,多道系统中,内存里同时存在多个进程。对每个进程内部而言,它所有代码、数据使用的地址都是自己的逻辑地址(从零开始编址)。如果每个进程都使用自己的逻辑地址在内存中存取信息,必然因为相同的逻辑地址而产生冲突。于是需要把不同进程的相同逻辑地址,映射到物理内存的不同地址。
补充一下,进程的逻辑地址空间按如下方式分配:
请注意,按照我的理解,这是逻辑地址空间,他们实际在内存的存放区域不一定是这样连续存放的。
分区存储管理
分区分配中,内存被分成若干个分区,每个分区容纳一个进程(书上写的是作业,但按个人理解,普通PC上应该是不需要作业调度的?)。于是每个进程的0号逻辑地址,就对应该分区物理地址的起始地址。
为了管理分区,设置一张不属于任何进程的分区说明表,如下图:
于是每个进程在分区说明表找到自己对应的表项目,根据表中的物理起始地址+自己的逻辑地址,就得到了实际的物理地址!目前为止需要注意的是,分区分配中,每个进程的分配的物理空间仍然是连续的!
关于分区分配更多的内容,不是这里的讨论主题,因此忽略。
分页存储管理
分区分配中,进程存放在连续的内存区域,可能会产生内部碎片。而分页存储管理,能够允许进程存放在多个不相邻的内存区域。
在分页存储管理中,将进程的逻辑地址空间分成若干大小相等的区域,称为页或者页面;相应地将物理内存空间划分成与页大小相等的区域,称为块或物理块。于是,进程的一个页面与内存的一个物理块一一对应(分区分配是整个进程和内存的一个区对应)。
为了管理分页,系统为每个进程设置一张页表,它将进程的页号映射到物理块号。请注意,这时地址的表示方式发生了变化,逻辑地址:页号+页内位移;物理地址:块号+块内位移(逻辑地址和物理的编址方式任然是从零到最大进行编址,但是在计算的时候需要拆分成页号和页内位移等)。完成地址映射的过程如下所示:
目前需要注意的是,分区和分页,逻辑地址空间都是线性的,虽然表示方式不同但都是按照从低(0开始)到高的一维线性排列。
关于快表和多级页表,不是这里的讨论重点,忽略。
分段存储管理
程序员一般希望按照逻辑管理系将进程分段(如程序段、数据段等),每个段逻辑上相对独立,段内从0开始编址。因此,整个进程的逻辑地址空间是二维的。如下图所示:
为了管理分段,系统为每个进程设置一张段表,它保存了进程每个段的段号、起始地址、段长信息,完成从段号到段基址的映射。请注意,这时地址的表示方式发生了变化,逻辑地址:段号+段内位移;物理地址:仍然是从零到最大值进行编址!。完成地址映射的过程如下所示:
8086采用的就是段式存储管理,通过段基址+段偏移找到物理地址。
区分段式和页式,主要在于一个的地址空间是二维的,一个的地址空间是一维的。
段页式存储管理
简单来说,就是在分段的基础上进行分页!