操作系统之存储管理

来源:互联网 发布:vb与c#语法区别大吗 编辑:程序博客网 时间:2024/05/01 22:12
3.1无存储现象
早期的计算机没有存储器抽象 内存基本上只能放一个程序来运行
3.2 存储器抽象:地址空间
物理地址暴露给进程的问题:
1如何用户可以寻址内存的每个字节,那么他可以随意的破坏操作系统,除非有硬件保护
2很难实现多个程序交替运行
地址空间:一个进程可以用于寻址的地址集合

基址寄存器和界限寄存器
  当一个进程在运行的时候,程序的起始物理地址装载在基址寄存器中,长度在界限寄存器中
  缺点:1每次寻址都要进行加法减法 浪费时间
3.22交换技术
内存超载的解决策略:
1 交换技术,将进程不运行的时候存回磁盘,
当进程在创建的时候应该给他分配内存的大小,面对进程大小会改变的 需要分配空闲的内存
在进行交换的时候应当移动实际被占用的  空闲内存不必移动
3.23空闲内存管理
跟踪内存使用的两种方法
1使用位图存储管理, 使用一块内存映射整个内存区域,将内存分为一块一块的(小到几个字,大到几千个字),
内存大小和每个单元大小决定了位图的大小
主要问题:在决定把一个占K分配单元进程调入内存时候,必须搜索位图,找到连续空闲区域 查找是个耗时的操作
2使用链表的存储管理 ( 类似于单链表)(也可以使用双链表)
每一个节点包含:空闲区H或者进程P的标志,起始地址,长度,指向下一个节点的指针
优点:进程在更换或者终止的时候更新非常直接
为进程分配内存的算法
1首次适配法
    沿着链表搜索 直到找到一个足够大的空间(速度很快)
2 下次适配法
     和1类似 但是不是每次从头开始,而是接着上次的地方搜索,(性能略低于首次适配法)
3 最佳适配法
    搜索整个链表 找到最适合进程的空闲内存大小,(性能不如首次适配法 而且容易产生很多的空闲碎片)
4进程和空闲区使用不同的链表,可以按照大小对空闲区进行排序
5快速适配法
    它为常用大小的空闲区维护单独的链表,第一项4K,第二项8K如此来分配
    缺点:大量无用的小的空闲区


3.3虚拟内存
虚拟内存的基本思想是:每个程序都有自己的地址空间,被分为很多块,每一个被称为一页或者页面,这些页都被映射到物理地址上面,并不是所有的页都在内存中才可以运行,部分就可以,
3.31分页技术
在使用虚拟内存的情况下,虚拟地址被送到MMU(内存管理单元,位于CPU内部)然后映射成物理地址
虚拟空间按照大小划分为称为页面的单元,在物理内存中对应的是叶框,一般来说 虚拟地址要比物理地址大很多,所以只有部分可以映射到物理地址,比如64K虚拟地址。32K物理地址 那么其中有32K地址在硬件上用一位(在/不在)表示是否映射,
虚拟地址由页号和偏移量组成 比如16位地址 前四位为页号,后12位是偏移量

页号作为索引来查询MMU中的页表,然后找到所对应的页框号,页框号和偏移量组成物理地址,发送到总线,


页表项的结构
32位为常见大小 包括3位控制读写执行  记录页面的使用状况“保护”位和“访问位” 最后一位是控制禁止高速缓存
当页面在内存中的时候 这时候页表项才包含这个页面
3.33 加速分页过程
主要问题1虚拟地址到物理映射必须非常的快
2虚拟空间很大 页表也会很大(64位机器虚拟地址超乎想象)

解决方法
 1TLB转换检测缓冲区 放在MMU中,包含少量的页项 一般不超过64个,每个表项记录了一个页面的相关信息,可以直接映射到物理地址,
工作过程,虚拟地址首先查询TLB,如果有有效的匹配而且不违反保护位,直接映射到物理内存,如果没有 就正常的访问页表,然后用新的页表代替TLB其中的一个页表
TLB可以加速虚拟地址到物理地址的映射
处理巨大的虚拟内存空间 使用多级页表技术
原因:避免将所有的页表放在内存当中,如32位虚拟地址划分为10位的P1域,10位的P2域,12位的偏移量,因为偏移量为12位 所以页面长度为4K一共有2的20次方个页面


工作过程:MMU提取P1作为索引 由此查询到二级页表的地址或者页框号,然后用P2域查询二级页表,找到物理映射地址
实际上只需要顶级页表,正文页表,数据页表,堆栈页表4个


先简述下问题所在:64位计算机中,如果页面大小为4KB,那么64位寻址空间需要252个页表项。假设每个页表项大小为8B,那么需要30PB的空间,在目前计算机发展阶段显然是不现实的。

  倒排页表是一种解决方案,正如其名所揭示的:普通的页表是将虚地址映射成物理地址,提供的是将页号(page number)转化为页框号(page frame number)的对应;这个转化由MMU完成;而倒排页表正相反,提供的是将页框号转化为页号的对应。页框号是实际内存的大小/页面大小,因此1GB内存只需要262,144个项即可,远远小于252这个数字。

  个人认为,这个解决思路的妙处在于:32位下,页表项总和比较少,至多两级页表也已够用;而64位下,内存的大小(也即物理地址空间)与寻址空间(虚地址空间)相比反而显得小了,这样干脆来个倒转,不失为一个很好的方法。

  当然这种解法虽然节约了大量的存储空间,但是内存管理中需要的是将虚地址转化成物理地址的机制,而不是正相反啊?这种映射是单向的,总不能每次转化都把这个表遍历一次吧?那样做的开销实在是太大了。

  一种解决方法是使用TLB,但是TLB也有失效(miss)的时候,这时还是需要进行查找。一个可行的方法是将所有用到的虚地址hash掉,形成一个hash表来加速查找,同样哈希值的虚地址形成一个链。如果hash表的槽数与物理内存的页框数一样多,那么哈希表各表项平均长度为1,这样提高了查找速度。



页面置换算法

当出现缺页中断的时候 必须使用页面置换算法来选择换掉哪一个页面

1最优页面换法
    理论上存在的算法


2最近未使用页面置换算法(NRU)
在虚拟内存地址中。有两个状态位,页面是否被访问M位,页面是否被修改R位 如果没有这样的设定,也可以用软件模拟这个
算法:当起动一个进程的时候,所有的R M位都被设置为0,当每次时钟中断的时候,R清零,当发生页面中断的时候,操作系统开始分类
1没有被访问 没有被修改
2没有被访问  被修改(时钟中断的清零会导致这种情况)
3被访问 没有修改
4被访问 被修改
优点:易于理解和实现,缺点 性能不是最好的,够用

3先进先出置换算法(FIFO)  不好用
4 第二次机会置换算法

对FIFO的修改,每次检查最老R位,如果这个R为0 说明既老又没人用,可以换掉,如果是1 就把1清零,放在链表的尾部

5时钟页面置换算法
将所有的页面保存在一个环形链表中,发生缺页中断的时候就检查指针所指的地方 也称为时钟算法
6最近最少使用页面置换算法(LRU)
在理论上可以实现 但是代价很高,(跳过)

软件模拟LRU
方案1 NFU 最不常用算法
该算法给每一个页面与一个计数器连接起来 ,每次发生时钟中断就会将R位的数字加在计数器上,这样子 发生页面中断的时候就可以去掉计数器最小的页面、
问题:从来不忘记任何事情

改进算法  老化算法
修改:1在R位加进去的时候,先将计数器右移动一位, 然后将R加在计数器的左边


7工作集页面置换算法
(实现起来开销很大)在某个时刻 需要的页面的集合被称为工作集,然后每次进行访问的时候就进行判断,使用的页面放在工作集,不用的踢出去
8工作集时钟算法(不明白)

3.5分页系统的设计问题

3.51全局分配策略和局部分配策略
(跳过)
3.52负载控制
减少内存竞争的方法是拿一部分的进程放到磁盘当中

3.53页面大小
最佳的页面大小需要几个矛盾的因素进行权衡
小页面可以节约内存 但是又会导致页表更大 效率也会降低

3.56 分段(跳过)


   
0 0