操作系统-内存管理

本文最后更新于:1 年前

[TOC]

分段管理

image-20210801212559233

image-20210801214351270

进程的地址空间:按照程序自身的逻辑关系划分(代码段,数据段……)为若干个段,每个段都有一个段名(在低级语言中,程序员使用段名来编程),每段从 0 开始编址。
内存分配规则:以段为单位进行分配,每个段在内存中占据连续空间,但各段之间可以不相邻。

由于是按逻辑功能模块划分,用户编程更方便,程序可读性更高。

逻辑地址:段号:段内地址

段表:段号=段基地址=段长。
缺点:

  • 内存碎片。
  • 内存交换效率低。

分页管理

分页式

  • 固定分区会产生碎片。把内存划分为很多块,作为进程内存分配的最小单位。

  • 页面大小要权衡,应该是 2 的幂次。太大会产生页内碎片,太小,页表会占用大量内存,降低换入换出效率。
    分页管理的地址结构:页号:页内偏移量

    为 32 位,0-11 为页内偏移,12-31 为页号。

    每页大小 2^12=4kb。

  • 为了方便每个进程在内存中找到每个页面对应的物理块,会为每个进程创建一张页表(存储在内存中===访问一次数据需要访问两次内存)。
    页表由页表项组成第一部分是,页号,第二部分是物理块号。

image-20210801213808642

分页管理问题

  • 每次访问内存都需要进行地址的转换。速度受限制。
  • 页表不能太大,否则内存利用率会降低。

改进

  • 具有并行查找能力的高速缓冲存储器==快表(联想存储器 TLB)–把最常访问的⼏个⻚表项存储到访问速度更快的硬件。

  • 这时先查快表,没有再查慢表。(局部性原理)

多级页表

  • 虚拟内存地址空间 4Gb,页表大小是 4kb,需要 100 万个页,假设每个页表项大小为 4b。那么需要 4Mb 来存储页表。

  • 每个进程都有自己的页表,假设有 200 个进程,就需要 800Mb 来存储页表,很大了。

  • 建立上一级页表存储页表间的映射关系。

  • 顶级页表一般只有一个页面。

建立多级页表:建立索引,不用去存储无用页表项,也不用去盲目的查找页表项。

image-20210801213945467

段页式管理

  • 分段利于反应程序的逻辑结构以及段的共享
  • 先将程序划分为多个有逻辑意义的段,接着再把每个段划分为多个⻚,也就是对分段划分出来的连续空间,再划分固定⼤⼩的⻚;
  • 地址结构就由段号、段内⻚号和⻚内位移三部分组成。
  • ⽤于段⻚式地址变换的数据结构是每⼀个程序⼀张段表,每个段⼜建⽴⼀张⻚表,段表中的地址是⻚表的起始地址,⽽⻚表中的地址则为某⻚的物理⻚号。

image-20210801214844351

  • 第⼀次访问段表,得到⻚表起始地址;
  • 第⼆次访问⻚表,得到物理⻚号;
  • 第三次将物理⻚号与⻚内位移组合,得到物理地址。

虚拟内存

基于局部性原理:程序装入时,先装入一部分,其他的驻留在外存,当访问的信息不在内存时,再换入。
这好像给用户提供了一个比实际内存大的内存空间。

使用外存的空间来扩展内存的空间。
实现:
分页
分段
段页式
需要:
内外存
页表机制
中断机构(缺页中断)
地址变换(先检索快表)

总结

为了在多进程环境下,使得进程之间的内存地址不受影响,相互隔离,于是操作系统就为每个进程独⽴分
配⼀套虚拟地址空间,每个程序只关⼼⾃⼰的虚拟地址就可以,实际上⼤家的虚拟地址都是⼀样的,但分
布到物理地址内存是不⼀样的。作为程序,也不⽤关⼼物理地址的事情。

每个进程都有⾃⼰的虚拟空间,⽽物理内存只有⼀个,所以当启⽤了⼤量的进程,物理内存必然会很紧
张,于是操作系统会通过内存交换技术,把不常使⽤的内存暂时存放到硬盘(换出),在需要的时候再装
载回物理内存(换⼊)。

那既然有了虚拟地址空间,那必然要把虚拟地址「映射」到物理地址,这个事情通常由操作系统来维护。
那么对于虚拟地址与物理地址的映射关系,可以有分段和分⻚的⽅式,同时两者结合都是可以的。

内存分段是根据程序的逻辑⻆度,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的
段,同时是⼀块连续的空间。但是每个段的⼤⼩都不是统⼀的,这就会导致内存碎⽚和内存交换效率低
问题。

于是,就出现了内存分⻚,把虚拟空间和物理空间分成⼤⼩固定的⻚,如在 Linux 系统中,每⼀⻚的⼤⼩
4KB 。由于分了⻚后,就不会产⽣细⼩的内存碎⽚。同时在内存交换的时候,写⼊硬盘也就⼀个⻚或
⼏个⻚,这就⼤⼤提⾼了内存交换的效率。

再来,为了解决简单分⻚产⽣的⻚表过⼤的问题,就有了多级⻚表,它解决了空间上的问题,但这就会导
致 CPU 在寻址的过程中,需要有很多层表参与,加⼤了时间上的开销。于是根据程序的局部性原理,在
CPU 芯⽚中加⼊了 TLB,负责缓存最近常被访问的⻚表项,⼤⼤提⾼了地址的转换速度。

Linux 系统主要采⽤了分⻚管理,但是由于 Intel 处理器的发展史,Linux 系统⽆法避免分段管理。于是
Linux 就把所有段的基地址设为 0 ,也就意味着所有程序的地址空间都是线性地址空间(虚拟地址),相
当于屏蔽了 CPU 逻辑地址的概念,所以段只被⽤于访问控制和内存保护。

另外,Linxu 系统中虚拟空间分布可分为⽤户态和内核态两部分,其中⽤户态的分布:代码段、全局变量、
BSS、函数栈、堆内存、映射区