OS笔记(一) 内存管理

内存管理方案

1. 无存储器抽象

最原始的方案,每个程序都直接访问物理内存。这种方案下有三种内存的组织方式:

  • 操作系统位于内存顶端的ROM(只读存储器)中
  • 操作系统位于RAM(随机访问存储器)中
  • 设备驱动位于内存顶端的ROM中,OS的其他部分位于RAM的底部
    在这种没有内存抽象的系统中,想实现并行可以使用多线程编程。

2. 地址空间抽象

1.地址空间

把物理地址暴露给程序的弊端:

  • 如果用户程序可以寻址内存的每个字节,就有可能破坏OS
  • 难以实现多进程
    所以引入了地址空间的概念,为程序创造一种抽象的内存。地址空间是一个进程可以用来寻址内存的一套地址的集合,每个进程都拥有自己的地址空间,且这个地址空间独立于其他进程的地址空间,仅在特殊情况下,进程可以共享地址空间。

地址空间的实现:
利用基址寄存器与界限寄存器,把每个进程的地址空间映射到物理内存的不同部分。一个进程运行时,其起始物理地址被装载到基址寄存器里,长度被装在到界限寄存器里。在进程访问内存时,CPU在把地址发送到内存总线前会自动加上基址,同时检查是否超越了界限。

2. 交换技术

因为物理内存的大小不足以容纳所有进程,交换技术即在进程运行的时候将其导入内存,空闲时再存入磁盘。因为很多编程语言都可以动态分配内存(堆),交换时在内存中为进程预留一些空间,在换出时,只需要交换进程实际上使用的内存。

空闲内存的管理
1. 位图

将内存划分为很多分配单元,每个对应位图中的一位,0表示空闲,1表示占用。
这种方法利用一块固定大小的内存区就可以管理整个内存,但是位图是一个线性的存储结构,查找可用内存块非常耗时。

2. 链表管理

这种方法维护一个记录内存使用情况的链表,链表的每个节点包含一个进程,或是两个进程之间的空闲区域,按照地址排序。寻找空闲区域有以下几种方法:

  • 首次适配 First Fit:沿着链表一直搜索,直到找到一个足够大的空闲区域
  • 下次适配 Next Fit:每次找到合适空闲区域的时候都记录当前位置,以便下次寻找时搜索
  • 最佳适配 Best Fit:总是分配能容纳进程的最小的空闲区域
  • 最差适配 Worst Fit:总是分配最大空闲区域
  • 快速适配 Quick Fit:为常用大小空闲区维护单独的链表

3. 虚拟内存

每个程序拥有自己的地址空间,被分割为很多块,这些块称之为页面 Page,每页都拥有连续的地址范围,并且被映射到物理内存。并非所有的页都位于内存中才能运行程序,当程序引用了内存中的地址时,由硬件立即映射,当程序引用了不在物理内存中的地址空间时,由操作系统负责将缺页装入内存(即缺页中断)。

1. 分页

程序产生的地址,即程序的汇编代码中使用的地址,称为虚拟地址,他们构成了虚拟地址空间。不使用虚拟内存时,系统会直接将虚拟内存送至内存总线,而使用虚拟内存时,虚拟地址会被送至内存管理单元(Memory Management Unit,MMU),由MMU负责把虚拟地址映射为物理地址。

2. 页表

虚拟地址被分为虚拟页号(高位)和偏移量(低位),页号指定虚拟页面中的一页,偏移量确定在页面中的偏移量。页表是以虚拟页号作为索引,用于寻找页框号的结构。页表项是一个负责管理页表的数据结构,包含高速缓存禁止位、访问位()、修改位、保护位、“在/不在”位(表示该页在不在内存中)和页框号(页表映射的目的)。

3. 页面置换算法

为了使常用的页面保留在内存中,减少置换开销,提出了缺页置换算法

1. 最优页面置换算法
2. 最近未使用算法NRU Not Recently Used

添加两个状态位:R位和M位,页面即将被访问时设置R位,页面被写入时设置M位。启动一个进程时,它所有的页面的两个位都置0,R位被定期置0。发生缺页中断时,检查所有页面并根据当前RM位的值,把页面分为四类:

  • 0:未访问、未修改
  • 1:未访问、已修改
  • 2:已访问、未修改
  • 3:已访问、已修改
    NRU随机从类号最小的非空类中挑选一个页面淘汰之。
3.先进先出算法FIFO First In First Out

由系统维护一个页面的链表,最新进入的页面放在表的尾部,最久的放在表头,缺页中断时,淘汰表头的页面,把新的页面放在表尾

4. 第二次机会算法

在FIFO的基础上添加检查最老页面的R位,若为0,则置换掉,若为1,则将R位清0,并将页面放到链表的尾端

5. 时钟算法

把所有页面保存在一个环形链表中,一个指针指向最老的页面,缺页中断时,检查指针所指页面,若R为0则淘汰,把新页面插入此位置,若R为1则指针前移,重复直至找到R为0的页

6.最近最少使用算法LRU Least Recently Used

维护一个所有页的链表,最近最多使用的在表头,最近最少使用的在表尾

7. 最不经常使用算法NFU Not Frequently Used

将每个页面与一个软件计数器相关联,计数器初值为0,每次时钟中断时,由OS扫描所有页,将R加在计数器上,这个计数器可以大体表征每个页面的使用频率,缺页中断时,置换计数器最小的页面

4. 缺页中断的细节
  1. 硬件陷入内核,离开当前进程,保存程序计数器
  2. 启动一个汇编代码例程保存通用寄存器
  3. OS发现缺页中断,尝试发现需要的虚拟页面,若未在寄存器中发现,则检索程序计数器取出指令进行分析,找到缺页
  4. 检查缺页中断的虚拟地址后,检查是否有效,并检查存取与保护是否一致,若检查不通过则发送信号杀死该进程。若检查通过,则检查是否有空闲页框,若无,则执行置换算法淘汰一个页面
  5. 若选择的页框已经脏了,即已经修改过了,安排该页写回磁盘,发生上下文切换,此时需要先挂起缺页中断进程,等待磁盘I/O
  6. 页框干净之后(立即或写回磁盘后),OS查找所需页面的地址,装入内存,页表更新位置,页框标记为正常,重新唤醒进程,从缺页之前的指令开始执行
5. 分段

概念:在机器上提供多个相互独立的地址空间,称之为段 Segment,每一段都由一个从0开始的线性地址序列构成,不同的段长度不同,运行期间可以动态改变段长度,诸如堆段、栈段的长度可以增长
分段的优势:

  • 程序更新变大后,过程中的地址不需要修改。在不分段的情况下,过程的大小会影响其他过程的地址
  • 有助于进程间共享过程和数据,例如共享库,把一个库放在一个单独的段中被所有进程所共享
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值