物理内存管理为程序运行提供服务。程序驻留在外存,并使用逻辑地址。
逻辑内存管理的核心工作:逻辑地址空间到物理空间的映射。
逻辑内存管理方式:区式、段式、页式、段页式。
一、区式管理法
物理内存采用静态或动态分区法管理。在加载时,为程序分配一个足够大的区,其内存在物理上是连续的,起始地址为Base。将程序整个装入到区中。
采用静态或动态重定位技术,完成逻辑地址到物理地址的转换。只需要记录区的基址和界限。基址用于地址转换,界限用于越界检查。
二、段式管理法
1、物理内存采用静态或动态分区法管理。根据进程对各段的要求,可为其分配多个小内存块,每块用于一个段。
2、进程由代码、数据、堆栈等组成。
每个进程一个段表,段表中的每一项是一个段描述符,描述各区的开始位置、界限、保护信息。
保护信息由访问方式(只读、读写、执行)、特权级等。
Intel处理器提供6个段寄存器:CS、DS、ES、FS、GS、SS,记录当前正在使用的段描述符。
Intel 的段描述符
3、
在段式管理中,程序中使用的逻辑地址由段号和偏移量组成。
段号:在进程段表中的序号,用来确定区的开始位置和界线。偏移量:相对于分区开始位置的偏移量,即相对地址,用来定位内存单元。
地址转换需要硬件支持:由硬件机制动态地完成逻辑地址到物理地址的转换。
每一次地址转换之前都要做合法性检查(硬件完成,不可屏蔽)通过才可进行地址转换访问段中内容,越界和不合法访问不能转换时产生异常。
4、段式管理可以实现内存共享
若一个段描述符放在多个进程的段表中,这些进程就都可以访问到它的内容。
5、段式管理的特点、优缺点
一个进程可以占用多个小分区,各小分区之间可以不连续,尺寸可以不一样(动态分区)。
不存在内部碎片(动态分配);由于分区变小,外部碎片也随之变少。
可以以小分区为单位换入/换出。需要为每个进程提供一个段表,进程切换时,段表也要随着切换。
优点:
用户的逻辑地址空间可大于实际的物理内存空间,可为多道程序运行提供支持。
便于动态连接,从而避免静态连接造成的某些时间和空间的浪费。
缺点:复杂,增加硬件成本和软件开销。段的基地址和大小不规整,随意。
段式管理的实质是动态分区法。
三、页式管理法
1、
段式管理只能缩小却不能消除外部碎片,且段的尺寸不规整。
页式管理:① 缩小分区的尺寸,使各分区足够小。② 允许为进程分配多个分区,分区之间可以不连续。
基本思想:
给一个进程分配多个小的分区,属于一个进程的小分区可以不连续。消除了外部碎片,减少了内部碎片(允许内部碎片)。可以以小分区为单位换入/换出。允许进程部分驻留内存。
2、帧
小分区采用等尺寸分区。将物理内存预先分成多个等尺寸分区,称为帧(Frame),帧号能完全描述一个帧。
等尺寸分区的内部碎片平均占半个区。大帧管理结构少;内部碎片大,小帧反之。
帧过大 --> 变为静态分区;帧过小 --> 变为动态分区
为便于管理,帧的尺寸应该是2的指数,研究得到,应在512到8192间。
Intel 处理器的帧尺寸是 4096 字节(4K)。Intel处理器还有4M(1024个页)、2M 的页。
3、页
操作系统自动将进程的逻辑地址空间分割成小块,大小与帧相同,称为页。
以页为单位为进程分配物理内存。当要加载(换入)进程时,根据进程的页数为其分配帧,将一个页加载到一个帧中。
(物理地址空间 --> 帧 ; 逻辑地址空间 --> 页)
进程在内存中占用的帧可以不连续。物理上不连续,逻辑上连续。
不需要用户参与,规整,便于虚拟化。
4、页表
(1)逻辑地址分为两部分:页号、偏移量
物理地址分为两部分:帧号、偏移量
逻辑地址到物理地址的转换需要知道每个进程页对应的物理帧,以及每个帧的基地址。
记录页与帧对应关系的表称为页表。
逻辑地址中的偏移量与物理地址中的偏移量相同,所以将逻辑地址中的页号换成帧号就得到了物理地址。查表慢,所以地址转换需要硬件加速。
(2)每个进程都需要一个页表。
处理器提供一个专用寄存器(PTBR)用于记录当前进程的页表基地址。
每次地址转换都需要多次访问内存,大大降低了访存速度,所以通常由处理器提供快速查找缓存TLB(Translation
Look aside Buffer),在其中缓存最近使用的页表项。
(3)共1M个页,如果一个表项占用4个字节,则一个页表需要4MB的内存。
很多进程不会用满自己的逻辑地址空间,它的页表的大部分是空的,没有必要为每个进程都预先建立4MB的页表。
(4)解决:将页表分级,变单级页表为多级页表。
分级以后,进程的一级页表必须存在(保存在进程的PCB中)。二级页表可以不连续,可以不存在,甚至可以被换出/换入。通常情况下,二级页表是动态创建的,大大减少了页表占用的内存量。
**** 页目录 --> 页目录项是页表在内存的位置 --> 一个进程一个页表 --> 页表项是逻辑页与物理帧的对应关系以及一些控制关系 ****
(5)页表项中为帧号和保护信息
Intel的页表项
这是硬件做的。
脏标志:是否被更改过
存取标志:是否被访问过(不用时可以把部分页换出,换谁?看最近没用过的)
用户/超级用户标志:特权级
读/写标志:读写权限
存在标志:这个逻辑页对应的物理页是否存在,即是否占内存
5、处理器产生的逻辑地址并不直接送到地址总线上,而要经过内存管理单元(MMU)的处理,MMU负责完成地址的转换。
CPU把逻辑地址给MMU,MMU把物理地址给内存。
6、管理物理帧和页的分配和回收 --> 以帧或页为单位,采用伙伴算法
7、在Intel处理器开机时,页式管理被关闭,需要显式将其打开。启动页式管理的方法:
① 定义页目录/页表。② 将页目录的地址加载到CR3中。③ 将CR0的第31位置1。
打开之后,所有的地址都需要经过页目录/页表转换(所以地址都是逻辑地址)。
8、(1)何时建立页表 :(Lazy)程序运行时还未建立页目录、页表,便会产生异常 --> 异常时建
(2)如何定义也目录、页表:只要建立起来进程逻辑地址空间与系统物理地址空间的映射关系即可,每个逻辑页对应一个物理帧。
(3)内核放在1M处,逻辑地址放在3G+1M处,要提前把关系建好(一一对应,差3G)
(4)进程运行过程中要不断访问内核,进程的运行离不开内核的支持。
所以将内核嵌在每个进程的逻辑地址空间中,使每个逻辑地址空间都有内核。但在物理地址空间中仅有一个内核,它被所有的逻辑地址空间共享。
为了方便,内核一般放在逻辑地址的高端。在32位处理器中放在 3GB~4GB 之间。内核的逻辑地址的起始地址是0xC0100000(ucore的起始逻辑地址是0xC0000000)
做好的页目录、页表
若超过2G,只有1G在内核有地址,剩余的内核中没有预先分配地址,为HIGHMEM(高端内存),内核访问不到,用户可以。所以内核中不要把1G用满,留下一块,用时给他临时分配一个逻辑地址,用完释放掉。
eg;逻辑上用户没问题,一页一页连续的,内核不行,Linux 内核中留了128M,用来临时分配。
四、段页式管理法
1、
段式和页式各有优缺点。Intel处理器采用段页式内存管理。
段式是必须的,段内内存可以再分页。
段由段描述符表描述,如GDT,页由页目录、页表描述。
逻辑地址需先经过段描述符表转化成线性地址,再经过页目录、页表转化成物理地址。
示意图
2、Intel 处理器汇总段式管理不可关闭,但应尽量避免
方法:做四个重叠的大段
ucore 内核定义的 GDT(段描述符表)
分页机制启动后,GDTR 指向该 GDT 表。
由于各个段的基址都是0,界限都是最大,所以线性地址与逻辑地址相等,段的作用被屏蔽。起作用的是页式管理。目前的操作系统中使用的也都是页式管理。
TSS主要用于切换堆栈。当特权级发生变化时,处理器使用的堆栈也要切换,需要为每个进程至少定义2个堆栈。
3、TSS
TSS是一块内存空间,当前进程的系统堆栈的栈底保存在TSS中。
需在GDT中为TSS创建描述符,TR指向当前使用的TSS描述符(基址与界限)。
可以为每个进程创建一个TSS,进程切换时改TR;也可以让所有进程共用一个TSS,TR保持不变,进程切换时改esp0(ss0不变)。
ucore 采用的第二种方法。