第七章 内存管理

前言

  • 单道程序设计系统中,内存被划分为两部分:

    • 一部分供操作系统使用(驻留监控程序、内核);

    • 一部分供当前正在执行的程序使用。

  • 多道程序设计系统中:

    • 在内存中进一步细分出用户部分,以满足多进程要求;

    • 细分的任务由操作系统动态完成 — 内存管理。

一、内存管理需求

  • 重定位

  • 保护

  • 共享

  • 逻辑组织

  • 物理组织

1. 重定位

  • 程序员并不知道进程执行时在内存的位置

  • 进程可能被置换到磁盘,再次进入内存时将在不同的位置,需要重定位

    • 必须允许进程通过 swapping 技术在内存移动

    • 内存索引(逻辑地址)必须转换成进程的物理内存空间

第七章 内存管理_第1张图片
  • 重定位:将逻辑地址转换为物理地址

    • 当进程装入内存时,绝对地址是确定的;

    • 进程在执行期间,可能占据不同的分块(置换);

    • 压缩技术也可能会引起进程占据不同的分块

  • 地址类型
    • 逻辑地址(相对地址)

      • 程序中的访问地址,从 0 开始;
    • 物理地址(绝对地址)

      • 数据在内存的
重定位 — 过程
  • 系统采用运行时动态加载的方式把使用相对地址的程序加载到内存。

    1. 被加载进程中的所有内存访问都是相对于程序的开始点

    2. 需要一个硬件机制把相对地址转换成物理地址

      • 基址寄存器 — 载入程序在内存中的起始位置

      • 界限寄存器 — 程序的终止位置

      • 基址寄存器 + 相对地址 < 界限寄存器 — 提供保护

第七章 内存管理_第2张图片

2. 保护

  • 内存管理:避免内存中的进程间有意无意的互相干扰,防止地址越界和操作越权;

    • 用户进程不能访问 OS 的任何代码或数据;

    • 进程未经授权不能访问其他进程的内存单元,读或写;

    • 编译时不可能检查绝对地址来确保保护,必须在指令访问内存时判断访问是否违法;

  • 此需求必须由 CPU(硬件)来满足,而不是由 OS(软件)满足。

3. 共享

  • 允许多个进程访问内存的同一部分;

    • 多个进程属于同一个程序,每个进程访问程序同一个副本;

    • 合作完成同一个任务的进程可能需要共享访问相同的数据结构;

  • 必须允许共享区域进行受控访问

4. 逻辑组织

  • 程序被组织成模块
    • 某些模块可以独立地编写和编译;

    • 可以给模块不同程度的保护(只读 、 只执行);

    • 模块化易于被多个进程共享。

第七章 内存管理_第3张图片

5.物理组织

  • 存储器至少分为两级,如果程序员负责组织信息流

    • 供程序和数据使用的内存可能不足

      • 需采用覆盖技术来组织程序和数据,不会被同时调用的共同使用同一内存区

      • 浪费时间

    • 多道程序设计中,程序员并不知道可用空间的大小和位置;

  • 内存管理:需要 OS 移动信息完成存储管理功能。

二、内存分区

  • 内存管理技术:固定分区;动态分区;简单分页;简单分段;虚拟内存分页;虚拟内存分段。

  • 分页、分段:离散分配内存空间给进程的页或段

  • 分区:连续分配内存空间给一个进程

    • 固定分区

    • 动态分区

1. 固定分区

  • 系统将内存划分成若干边界固定的区域,设定分区说明表;

  • 分区大小相等:小于或等于分区大小的任何进程可以装入可用分区。

第七章 内存管理_第4张图片
分区大小不等:放置算法
  • 把每个进程分配到能够容纳它的最小分区;

  • 使得分区内部碎片最少;

  • 调度队列保存换出的进程

    • 每个分区一个队列或者只提供一个队列

      • 容纳新进程的最小分区;

      • 考虑优先级;

      • 被阻塞的进程。

第七章 内存管理_第5张图片
缺点
  • 分区数目固定,限制了活动进程数目;

  • 分区大小事先设置,小作业不能有效利用分区空间。

2. 动态分区

  • 分区的长度和数目是可变的;

  • 进程被精确分配在相应的内存空间。

第七章 内存管理_第6张图片
缺点:
  • 会产生很多空洞 — 外部碎片

  • 克服空洞,引入压缩技术

    • OS 不停移动内存中的进程,使碎片连成一片;

    • 费时,并要求动态重定位。

动态分配 — 放置算法
  • 最佳适配(Best Fit)

    • 空闲区按大小递增顺序排列,选择与要求的大小最接近的块;

    • 性能最差,更经常地压缩。

  • 首次适配(First Fit)

    • 开始扫描内存,选择大小足够的第一个可用块;

    • 低地址有许多碎片,高地址端有大空间可用;

    • 最简单的,最好的,最快的。

  • 下次适配(Next Fit)

    • 上一次放置位置开始扫描内存,选择下一个大小足够的可用块;

    • 末尾最大的存储块很快分成小碎片,需要多次压缩。

第七章 内存管理_第7张图片

3. 伙伴系统

  • 折中方案

  • 伙伴:两个大小相等的相邻分区;

  • 2^U 表示可用的整个内存的大小;

  • 算法:如果请求的大小 s 满足 2^(U-1) < s ≤ 2^U ,则分配整个空间;

    • 否则,分成两个大小相等的伙伴,均为 2^(U-1),如果有 2^(U-2) < s ≤ 2^(U-1),则分配其中任何一个;

    • 直到产生大于或等于 s 的最小块。

第七章 内存管理_第8张图片
第七章 内存管理_第9张图片

4. 分页

  • 内存被划分为固定大小的块 — 页框 frame

  • 进程也划分成同样大小的块 — 页 page

  • 此技术为每个进程浪费的空间仅仅是 一 小部分内部碎片

    • 最后一页产生内部碎片

    • 无外部碎片

第七章 内存管理_第10张图片
  • OS 需要为每个地址维护一个页表

    • 页表项包含内存中的用于保存相应页的页框号;

    • 进程进入内存分配页框,并创建页表

    • CPU 必须知道如何访问当前进程的页表

  • 逻辑地址包括一个页号和在该页中的偏移量

第七章 内存管理_第11张图片
第七章 内存管理_第12张图片
分页 — 地址装换
  • 地址转换步骤:
    • 提取页号;

    • 对应页号,找到页表中的页框号 k;

    • 物理地址:k * 2^m + 偏移量(m 是偏移量的位数)。

第七章 内存管理_第13张图片

练习题:页式存储管理系统中,某进程页表如下。已知页面大小为 1024 字节,问逻辑地址 600,2700,4000 所对应的物理地址各是多少?

第七章 内存管理_第14张图片

答:
逻辑地址 600 在 0# 页,放在 7# 页框。页内偏移地址为 600。
对应的物理地址为:600:7×1024+600=7768

2700 在 2# 页,放在 5# 页框,页内偏移地址为:2700 mod 1024=652
对应的物理地址为:2700:5×1024+652=5772

逻辑地址 4000 在 3# 页,越界

5. 分段

  • 分段技术:把程序和其相关的数据划分到几个段中,有长度限制,但不一定相等;

  • 逻辑地址 = 段号 + 偏移量

  • 段大小不等,类似于动态分区;

  • 段表给出相应的段在内存中的起始地址段的长度

  • 段表的地址装入寄存器,供内存管理硬件使用。

分段 — 地址转换
第七章 内存管理_第15张图片
第七章 内存管理_第16张图片
第七章 内存管理_第17张图片
分段 — 转换机制
第七章 内存管理_第18张图片

练习题:在一个简单分段系统中,包含如下段表:

第七章 内存管理_第19张图片

对如下的每一个逻辑地址,确定其对应的物理地址或者说明段错误是否会发生:

答:
a. 段 0 定位在 660,所以我们有物理地址 660 + 198 = 858。

b. 段 2 的起始地址是 222,222 + 156 = 378。

c. 段 1 长度为 422,所以会发生错误。

d. 996 + 444 = 1440。

e. 660 + 222 = 882。

三、安全问题

1. 缓冲区溢出(内存越界)

  • 输入到一个缓冲区或者数据保存区的数据量超过了其容量,从而导致覆盖了其他信息。

    • 可能由编程错误造成;

    • 会被攻击者利用,攻击系统

  • 错误后果:

    • 程序使用数据损坏;

    • 程序中控制流发生意外改变;

    • 违法的内存访问;

    • 程序终止。

  • 为了利用各种缓冲区溢出类型,攻击者需要

    • 找出程序中的外源数据触发的缓冲区溢出漏洞;

    • 了解缓冲区将如何在进程内存中存储,从而发现损坏相邻内存单元及改变程序执行流的可能性

  • 通过追踪程序可以发现易受攻击的程序;

  • 通过特定工具,可以自动发现潜在地易受攻击的程序。

预防缓冲区溢出
  • 编译时防御系统,强化系统以抵制潜伏于新程序中的恶意攻击 — 止执行缓冲中的代码;

  • 运行时防御系统,检测并中止现有程序中的恶意攻击 — 检测到异常及时中止。

四、补充内容

  • 覆盖技术:把一个程序分为一系列功能相对独立的程序单元,让执行时并不要求同时装入内存的单元成一组,共享同一个存储区域。

  • 覆盖技术要求程序员必须把一个程序划分成不同的程序段,并规定好它们的执行和覆盖顺序,操作系统根据程序员提供的覆盖结构来完成程序段之间的覆盖。

  • 交换技术(swapping):把暂时不用的某个程序及数据部分或全部从内存移到外存中去,以便腾出必要的内存空间,或把制定的程序或数据从外存读到相应的内存中,并将控制权转给它。

  • 覆盖主要在同一个作业或同一个进程内进行,并且只能覆盖那些与覆盖程序段无关的程序段;而交换主要是在进程或作业之间进行。

你可能感兴趣的:(第七章 内存管理)