考研408《操作系统》复习笔记,第三章《3.2.1 内存分配:连续分配》

考研408《操作系统》复习笔记,第三章《3.2.1 内存分配:连续分配》

本来是打算把整个内存分配两大块:【连续分配】+【离散分配】一起写完笔记,但是发现【离散分配】复杂到离谱,只能分开写了,本章节是《连续分配》

连续分配

就是顾名思义:【整个进程完整】地装入到【内存】,不去分割进程,一个进程在内存里是连续存放的

1、单一连续分配

【总结特点】

简单解释:

只用记住【只能允许一个进程独占】内存直到运行完,也就是【还没有操作系统诞生前的 单道程序环境】,既然没有多个进程分割内存那就【没有外部碎片】

2、固定分区分配

【总结特点】

简单解释:

  • 操作系统诞生了,要支持多个程序并发运行,那内存肯定得允许存放多个进程
    • 于是便为内存划分了很多分区,每个分区只给一个进程,每个进程根据【分区说明表】来选择空闲分区装入
    • 【相等分区划分】是事先规划了一堆相同大小的分区
      • 就像提前做了相等份量的预制菜的饭店
    • 【不相等分区划分】是事先规划了一堆大小不一样的分区
      • 就像做了不同分量预制菜的饭店

  • 那么【固定分区】里不管是【相等分区划分】还是【不相等分区划分】,都是在进程进入内存之前事先划分好的,不是完美动态适配进程需求的空间
    • 都必然会导致【内部碎片】,即【分区大小 > 进程实际所需大小】而浪费出空闲空间

【例题】

3、⭐动态分区分配(又叫“可变区分配”)⭐

为了更好地解决固定分区存在的问题(内部碎片),人们又提出了动态分区分配存储管理技术,基本思路如下:分区不是预先划分地固定区域,而是动态创建的,即装入一个程序时,系统根据它的需求和内存空间的使用情况决定是否分配。

(饭店根据客人来了亲口说的需求做饭,而不是做预制菜了)

1)简单解释规则

  • 一开始内存只有【空闲区】和【操作系统进程运行区】
  • 随后分别进入进程1、进程2、进程3,都是进程来了才动态根据【进程要多大,就给多大】分配,因此【每一个进程运行的分区】都刚好存满一个进程,【不存在内部碎片】
  • 而进程结束后会释放分区,然而由于各个进程没有连续挨着,因此【空闲区也不连续】,而离散的空闲区大小都无法满足新进程所需大小时,就会导致【外部碎片】!!!

2)所依赖的数据结构

(注意区分:【固定分区分配】的分区表数据结构记录的是【所有分区】的信息;【动态分区分配】记录的只是【空闲分区】的信息。)

3)动态分区算法

  • 1、首次适应算法
  • (详细画法)

    • 重点是:
      • 空闲分区【按 “地址” 升序排列】
      • 每次内存分配后对空闲分区表【无需排序】
      • 【缺点】:每一次分配内存都要【从头遍历到尾】,麻烦
      • 【优点】:因为每次都要从头先遍历低地址,就会让低地址小分区先分配给小进程,留出高地址的大分区给大进程使用(跟 “最佳适应算法” 优点一样)
  • 2、邻近适应算法
    • 重点:其实就是【循环执行首次适应算法】
    • 和【首次使应算法】相同部分:
      • 依旧从低地址往高地址升序排列空闲分区,每次从头往后遍历到合适的分区来分配
      • 每次内存分配后对空闲分区表【无需排序】
    • 和【首次使应算法】不同部分:
      • 采用【循环链表结构】,【循环遍历】
      • 【优点】:每次遍历【不会从头开始】,直接从【上一次遍历结束位置】继续遍历下去,内存分配速度快
      • 【缺点】:高低地址都有同等概率被新进程分割,那么【大空闲区】有可能被多个小进程分割成【小空闲区】,导致【小进程有小空间不用】、【大进程需要大空间却没有】
  • 3、最佳适应算法
    • 重点:
      • 按【空闲区 “容量” 递增排列】
      • 因为要排序,所以每次内存分配后都要对空闲分区表【重新排序!!!】
      • 【优点】:每次都先给小进程使用小分区,以防小进程占用分割大分区,从而留下大片大分区给大进程使用
      • 【缺点】:小分区被分割,只会分割留下更多超小的小分区而没法使用,导致大量【外部碎片】
  • 4、最坏适应算法
    • 重点:
      • 按【空闲区 “容量” 递减排列】
      • 因为要排序,所以每次内存分配后都要对空闲分区表【重新排序!!!】
      • 【优点】:每次都先给所有进程使用大分区,后续的小分区就不至于被分割成小到没法用,起码能够一些小进程使用
      • 【缺点】:大分区先被小进程分割的话,就导致没有足够大分区分配给大进程了
  • 5、伙伴系统(了解即可)
    • 虽非考纲内容,但24年出现真题考察
    • 原理就是只会认定【2的次幂】大小的空间作为【空闲分区】
    • 标准就是若进程大小为nKB,先按【2^i-1 < n <= 2^i】找到内存中2^i的空闲分区,若找到了就把进程装入
    • 如果【2^i-1 < n <= 2^i】在内存中找不到2^i的空闲分区
    • 那就接着再找 2^i+1 的空闲分区,如果找到了就把分区分成两半(因为2^i+1/2就是2^i啊,前面已经证明了n <= 2^i,说明分了一半的大小还是够装入进程)
    • 1半装入进程、另1半单独另成一个链表【另外要记住】:进程大小并不会完美适配2的次幂,所以伙伴系统一定会有比进程大的分区,就肯定是会有【内部碎片】
  • 6、【基于索引搜索的动态分区分配】
    • 刚刚学得【伙伴系统】就是一种,那么另外两种好像根本就不是考纲内容
    • 但是王道选择题里出了,我看了一会就烦了,所以我觉得只要知道【基于索引搜索的动态分区分配】是哪三个就行了,无需在意这三个的细节!!!
【总结特点】

4、例题