操作系统笔记:内存管理

操作系统内存部分的知识点总结

存储器的层次结构:

高速缓存Cache:KB~MB级、少量、高速、昂贵、易失;
内存:GB级、中等速度、中等价格、易失;
SSD:?00G级、较高速、价较高、非易失;
磁盘/外村:GB~TB级、低速、价廉、非易失;

内存:

系统区:存放操作系统;
用户区:存放用户程序和数据;

存储管理的任务

主要工作:将程序载入内存以让CPU执行;
目的:

  1. 将内存区域进行划分以容纳多个进程(多道程序设计);
  2. 有效分配内存以容纳尽量多的进程;

存储管理的要求

重定位;
保护;
共享;
逻辑组织;
物理组织;

重定位

逻辑地址/相对地址
逻辑地址:与内存内容无关的内存位置
相对地址:相对于某一点(通常是程序起始位置,也可能是段基址)的逻辑地址(如偏移地址);

物理地址/绝对地址
物理地址:内存的实际地址,也称为绝对地址;

多道程序共享内存技术要求程序使用相对地址以支持重定位:

  1. 程序员不知道程序在运行时在内存中所处的位置;
  2. 处于内存某一块区域的程序代码,在运行中可能被交换出(swap out)到外存,后来又被交换进(swap in)到内存的另外一块区域;
    重定位一般要求一定的硬件(CPU)支持。

保护

多道程序共享内存技术要求一个进程不能对其他进程进行有意或无意的非授权访问;
程序的内存引用只能在运行时检查:

  1. 重定位导致无法在编译时检查绝对地址;
  2. 多数程序设计语言允许地址的动态计算(如数组下标、指向某种数据结构的指针等);
  3. 保护机制通常整合在重定位硬件机制中(从软件上,开销太大,难以估计到所有情况);

共享

支持不同进程访问内存的同一区域;
可能情形:

  1. 同一程序的不同进程实例共享程序区
  2. 合作进程间共享某些数据结构;
    重定位机制通常也支持共享

逻辑组织

反映程序组织的逻辑性,采用某种模块化形式组织用户程序及数据;
模块化有利于设计期间的编程;
模块化有利于运行时刻的保护;
模块化有利于运行时刻的共享;

物理组织

物理组织是操作系统的责任(资源管理);
主存与辅存间的信息交换能更好地实现系统的目标;
程序员关心物理组织是不切实际的:

  1. 主存有限致使程序员采用覆盖技术,浪费程序员精力和时间;
  2. 多道程序环境中,程序员编写代码时无法预知可用主存的数量和位置;

覆盖技术和交换技术

在多道程序环境下扩充内存的方法;
覆盖技术主要用在早期的操作系统中;
交换技术被广泛用于小型分时系统中,交换技术的发展导致了虚存技术的出现;
共同点:

  1. 进程的程序和数据主要放在外存;
  2. 只有当需要执行的部分才放在内存;
  3. 内外寸之间进行信息交换;

覆盖技术(overlaying)

把程序划分为若干个功能上相互独立的程序段,按照其自身的逻辑结构,让那些不会同时执行的程序段共享同一块内存区域
程序员要向系统提供覆盖结构,然后由操作系统完成程序段之间的覆盖。

交换技术(swapping)

交换技术:

  1. 当内存空间紧张时,系统将内存中某些进程暂时移到外存(swap out),把外存中某些进程换进内存(swap in),占据前者原来所占用的区域;
  2. 交换技术其实是进程在内存与外存之间的动态调度;

与覆盖技术比较

  1. 交换技术不要求用户给出程序段之间的逻辑覆盖结构
  2. 交换发生在不同的进程或作业之间,而覆盖发生在同一进程或作业之内;
  3. 覆盖只能覆盖那些与覆盖段无关的程序段

分区存储管理技术

分区(partitioning):

包括固定分区动态分区
只在一些特殊场合使用(如内核存储管理);
在一些已过时操作系统中采用;

简单内存分页(不单独使用):

大小相等,需一次装入一个进程的所有页。

简单进程分段(不单独使用):

需一次装入一个进程的所有段。

虚拟内存分页:

不需一次装入一个进程的所有页。

虚拟内存分段:

不需一次装入一个进程的所有页。

固定分区

将内存划分成若干个固定大小的区域:等长或不等长;

等长分区

任何小于或等于分区大小的进程都可以全部载入某一可用分区中(无可用分区时,可以使用交换技术)
存在的问题:

  1. 若进程大于分区,则只能部分载入,要应用覆盖技术(将程序分为互相独立的程序段,然后共享同一块内存区域);
  2. “小”进程将产生内碎片internal fragmentation),导致内存利用率降低;
不等长分区

在一定程度上减缓了等长分区存在的问题(仍没有完全解决)

固定分区的放置算法

等长分区的放置算法:进程可以放到任意一个可用分区中;
不等长分区的放置算法:
多队列:为每个分区设立一个输入队列,中的进程只能使用对应的分区,某些队列为空时会造成内存空间的浪费。
单队列:只有一个输入队列,进程使用可容纳它的最小空闲分区(无可用分区时可“交换”)

固定分区优缺点

优点:相对简单,开销小;
缺点:分区数目预设(系统创建时),限制了活动进程数;分区大小预设,小作业不能充分利用其占用的空间;

动态分区

系统运行中分区数目和大小均可以改变:最初分区数为0,进程需要多少就给它分配大分区。
存在问题:外碎片(external fragmentation)
在这里插入图片描述
消除碎片:压缩(移动进程使相互紧靠,相当耗时并且需要进行动态重定位);

动态分区的放置算法

首次适配算法(first fit):从前端开始扫描内存,直到找到一个足够大空闲区域。(简单,且通常最好、最快);
下次适配算法(next fit,邻近适配):从上次分配结束的地方开始扫描内存,直到找到一个足够大的空闲区。(稍差于首次适配,通常分配位于内存末端的空闲区,致使大块空闲区很快被分裂,因此经常要“压缩”);
最佳适配算法(best fit):扫描整个内存,找出一个足够大的最小的空闲区。(通常最差,产生大量无用的小碎片,导致需要更经常的“压缩”);

伙伴系统

固定分区限制了活动进程的数量,而且内存空间利用率低;
动态分区维护复杂,而且需要额外的“压缩”开销;
折中方案——伙伴系统(buddy system)
伙伴系统的宗旨就是用最小的内存块来满足内核对于内存的请求。
可用内存块的大小为 2 K 2^K , L≤K≤U,最小块的大小为 2 L 2^L ,最大块的大小为 2 U 2^U
初始空间为大小为 2 U 2^U 的块;
若请求的空间大小 s < 2 U 1 s<2^{U-1} ,则对分现有块;
维护大小为 2 K 2^K 的所有空闲块的列表;

Linux内核的内存管理
Linux伙伴系统概述
Linux内核内存管理要在频繁申请/释放内存的情况下,避免内存碎片的产生。Linux采用伙伴系统解决外部碎片的问题,采用slab解决内部碎片的问题。
避免外部碎片的方法主要有两种:

  1. 利用非连续内存的分配;
  2. 用一种有效的方法来监视内存,保证在内核只要申请小内存的情况下,不会从大块的连续空闲内存中截取一段过来,从而保证了大块内存的连续性和完整性。
    Linux使用第二种方法来解决外部碎片的问题,就是著名的伙伴系统。

页式存储管理

分页(paging);
基本原理:

  1. 主存划分成许多等长的小帧(frame,框);
  2. 进程划分成若干(page),一个页的大小与一个帧的大小相等;
  3. 进程加载时,所有页面都被载入可用帧(空闲帧)(不要求连续),同时建立页表(page table)——简单分页的主要数据结构。
页表(Page Table)

OS通过页表的建立和维护进行内存管理:

  1. OS为每个进程建立并维护一个页表;
  2. 页表的每个表项包含该页在内存中对应的帧号(还包含保护共享等信息)
  3. 页表以页号为索引;
  4. OS另外还维护一个空闲帧的列表;
    在这里插入图片描述
简单分页中的重定位

程序中的逻辑地址由两部分组成

  1. 页号
  2. 页内偏移

CPU的一对寄存器记录当前运行进程的页表起始物理地址、页表长度;
(页号,偏移)→(帧号,偏移)
规定:页(帧)的大小必须为2的整数m次幂;
当页(帧)的大小为2的m次幂时,逻辑地址与相对地址一致;
例:16位编址,若页面大小为1K(1024),则需(低)10位表示页内偏移,剩下(高六位)表示页号:
相对地址为1502的逻辑地址=1024 + 478 = (1,478)
逻辑地址为(1,479)的相对地址=1*1024 + 478 = 1502;

页面大小为2的m次幂时,页面(逻辑地址)对程序员、编译器/汇编程序、链接成序都是透明的;
动态地址转换硬件实现容易:(n, m)页表→ (k,m)
在这里插入图片描述

简单分页的特点

类似固定分区,不同在于:

  1. 分页中的“分区”(页帧)非常小(从而内碎片也小);
  2. 分页中的一个进程可占用多个“分区”(页帧),不需要使用覆盖技术;
  3. 分页中不要求一个进程占用的多个“分区”(页帧)连续(为了充分利用空闲分区)。

存在问题:

  1. 不易实现共享和保护(不反映程序的逻辑组织);
  2. 不便于动态链接(线性地址空间);
  3. 不易于处理数据结构的动态增长(线性地址空间);

分段存储管理

基本原理:将程序及数据划分成若干段(segment)(不要求等长,但不能超过最大长度);进程加载时,所有段被载入内存可用区域(不要求连续),同时建立段表(segment table)

段表(segment table)

OS通过段表的建立和维护进行内存管理:

  1. OS为每个进程建立并维护一个段表;
  2. 段表的每个表项包含该段在内存中的起始物理地址、段长等(页表只包含帧号);
  3. 段表以段号为索引;
  4. OS另外还维护一个内存空闲块的列表;
简单分段中的重定位

程序中的逻辑地址由两部分组成:

  1. 段号;
  2. 段内偏移;

进程进入运行态时,其段表地址被载入CPU专用寄存器;
逻辑地址(n,m)→物理地址的转换过程:

  1. 根据n位计算段号
  2. 段号为索引到段表查找段的起始物理地址
  3. 比较偏移(m位)与段长(段表中的记录),若前者大,则为非法地址;
  4. 物理地址 = 段起始地址 + 偏移
    在这里插入图片描述

页式管理和段式管理的比较

分页是处于系统管理的需要,分段是处于用户应用的需要;
一条指令或一个操作数可能会跨越两个页的分界处,而不会跨越两个段的分界处(因为分段不要求等长);
页大小是系统固定的,而段大小则通常不固定;
分页的逻辑地址表示是一维的,即页号和页内偏移是通过一个地址计算出来的;
分段的逻辑表示是二维的,物理地址是由段号代表的段基址和段内偏移组成的(由两部分地址组成);
通常段比页大,因而段表比页表短,可以缩短查找时间,提高访问速度;
分段对程序员可见,从而可用来对程序和数据进行模块化组织;
分段方便实现模块化共享和保护,如程序可执行、数据可读写(段表表项要有保护位)。
在这里插入图片描述

动态分区管理和段式管理的比较

都存在外碎片,但分段中可通过减少段长来减轻外碎片浪费程度;
分段中一个进程可占用多个“分区”;
分段中不要求一个进程占用的多个“分区”连续(但一般要求一个段所占用的多个“分区”连续);

分页和分段的主要优缺点

分段克服了分页存在的问题(数据结构的动态增长、动态链接、保护和共享);
分段存在外碎片,分页只有小的内碎片分页内存利用率比分段高

发布了76 篇原创文章 · 获赞 10 · 访问量 8236

猜你喜欢

转载自blog.csdn.net/weixin_38742280/article/details/105312771