0.无存储器抽象
- 通常程序引用绝对物理地址
- 在嵌入式系统和智能卡系统中,比较常见
一.地址空间
地址空间是一个进程可用于寻址内存的一套地址集合
1.通常为每个CPU配置两个寄存器:基址寄存器与界限寄存器
- 基址寄存器:存储程序的起始物理地址
- 界限寄存器:存储程序的长度
2.当取址时自动将基址值加到进程发出的地址值上,检查该地址是否超过界限寄存器计算后的值
- 每次访问内存都要加法运算和比较,而加法运算比较耗时
3.交换技术
交换技术,把一个进程完整的调入内存,使该进程运行一段时间,然后把它存回磁盘
- 内存紧缩,交换在内存中产生很多个空闲区,通过把所有进程尽可能向下移动,有可能将小的空闲区合并成一个大块,但是这个操作非常耗时
- 另一种方案为提前预留出一些内存空间给进程,当交换时仅将实际使用的空间交换出去
- 也可分配一大块,上边为堆栈,下边为程序,程序上边为数据,中间空闲区域为堆,供给数据和堆栈使用
4.空闲内存管理
1)位图存储管理:每个分配单元对应于位图中的一位,0表示空闲,1表示占用(或相反)
- 分配单元越小,位图越大;反之位图越小,但可能最后一块浪费较多
- 查找指定长度的连续0串是耗时的,因为可能跨越字的边界?
2)链表存储管理:维护一个记录已分配内存和空闲内存段的链表,其中链表中的一个结点或者包含一个进程,或者是两个进程间的一个空闲区,P为进程,H为空闲区,X为终点
常用算法:
- 首次适配:沿着链表找到一个足够大的空闲区,占用部分或全部,剩下的部分为新的空闲区
- 下次适配:与首次相似,但需记住位置,用以下次查询,性能相对较低
- 最佳适配:找到空闲区刚好等于或略大于所需空间的区域,性能差,碎片多
- 最差适配:总是找到当前最大的空闲区分配,也不是最优
- 两个链表:一个存使用中的空间,另一个存空闲区,好处是可以提高上述算法效率,但是增大了复杂度,和内存释放难度(将释放进程从进程表中删除,再插入到空闲表),小优化:利用单链表中的空闲区,第一个字是当前空闲区大小,第二个字指向下一个空闲区,第三个依旧指向下一个顺序节点,如此不需要P/H位
- 快速适配:为常用大小的空闲区维护单独立链表,如4KB 8KB 12KB 等,21KB可以放在20KB表中,也可单独维护一个21KB
二.虚拟内存
基本思想:每个进程拥有自己的地址空间,这个空间被分割成多个块,每一块称作一页或页面,每一页连续的地址范围,并不需要全部页载入到内存中,当引用不在内存中的页时,由操作系统将缺失的页载入到内存,并重新执行失败的指令
1.分页
- 内存管理单元MMU
- 虚拟地址构成了一个虚拟地址空间
- 虚拟地址空间按照固定大小划分成称为页面的若干单元,在物理内存中对应的单元称为页框
- 页面和页框大小通常是相等的
- 缺页中断:当MMU注意到某页面没有映射,于是CPU陷入到操作系统,这个陷阱称为缺页中断。操作系统会找到一个很少使用页框并把它的内容存到磁盘(如果不在磁盘上),随后把需要访问的页面读到刚才回收的页框中,修改映射关系,然后重新执行引起陷阱的指令
- MMU如何完成映射操作,以16个4KB页面为例,输入16位虚拟地址,输出15位物理地址,其中低12位为偏移量,高四位为页号,第四位标记是否映射
2.页表
页表的目的是把虚拟页面映射为页框。从数学角度来说,页表是一个函数,它的参数是虚拟页号,结果是物理页框号。这个函数可以把虚拟地址中的虚拟页面域替换成页框域,从而形成物理地址。
1)页表项结构:
- 保护位:指出一个页允许什么类型访问。最简单的形式是一位,0表示读/写,1表示只读。更先进的方法是3位,分别表示读、写、执行
- 修改位:也称脏位,表示这个页面是否修改过,如果被修改过则必须写会磁盘,若未修改过且磁盘存在副本则直接丢弃
- 访问位:在该页被写或读时,标记该位,当发生缺页中断时,优先选择未标记访问的页面
- 高速缓存禁止位:禁止该页面被高速缓存。对映射到设备寄存器而不是常规寄存器非常重要,保证硬件是不断从设备中读数据而不是从缓存中
2)加速分页过程
主要考虑问题:
⑴虚拟地址到物理地址映射必须非常快
⑵如果虚拟地址空间很大,页表也会很大
现象:大多数程序总是对少量的页面进行多次的访问
转换检测缓冲区(Transl