操作系统原理之物理内存管理之非连续内存分配

内存管理单元

Posted by chensong on 2020-05-19 02::33::24

前言

正文

一,非连续内存分配的需求背景

1, 连续分配的缺点

  1. 分配给程序的物理内存必须连续
  2. 存在外碎片和内碎片
  3. 内存分配的动态修改困难
  4. 内存利用率较低

2,非连续分配的设计目标: 提高内存利用效率和概率灵活性

  1. 允许一个程序的使用非连续的物理地址空间
  2. 允许共享代码与数据
  3. 支持动态加载和动态链接

3,非连续分配需要解决的问题

  1. 如何实现虚拟地址和物理地址的转换 - 软件实现(灵活,开销大) - 硬件实现(够用,开销小)

4, 非连续分配的硬件负责机制

  1. 如何选择非连续分配中的内存分块大小
    • 段式存储管理(segmentation)
    • 页式存储管理(paging)

二,段式存储管理

1,段地址空间

  1. 进程的段地址空间由多个段组成
    • 主代码段
    • 子模块代码段
    • 公用库代码段
    • 堆栈段(stack)
    • 堆数据(heap)
    • 初始化数据段
    • 符号表等

    segmentation

  2. 段式存储管理的目的
更细粒度和灵活的分离与共享

segmentation_address

segmentation_address_jion

2,段访问机制

  1. 段的概念
    • 段表示访问方式和存储数据等属性相同的一段地址空间
    • 对应一个连续的内存“块”
    • 若干个段组成进程逻辑地址空间
  2. 段访问:逻辑地址由二元组(s,addr)表示
    • s – 段号
    • addr – 段内偏移 addr_p

address_biao

三,页式存储管理

1,页式存储管理的概念

  1. 页帧(帧,物理页面,Frame, Page Frame)
    • 把物理地址空间划分为大小相同的基本分配单位
    • 2的n次方, 如512,4096, 8192
  2. 页面(页,逻辑页面,Page)
    • 把逻辑地址空间也划分为相同大小的基本分配单位
    • 帧和页的大小必须是相同的
  3. 页面到叶帧
    • 逻辑地址到物理地址的转换
    • 页表
    • MMU/TLB

2, 页式存储管理的地址转换

  1. 帧(Frame)
    • 物理内存被划分成大小相同的帧内存物理地址的表示:二元组(f,o)
    • f – 帧号(F位,共有2^f个帧)
    • o – 帧内偏移(S位,每帧有2^s字节)

物理地址 = f * 2^s + o

frame_f_o

  1. 基于页帧的物理地址计算实例 ① 假定 - 16-bit的地址空间 - 9-bit(512byte)大小的页帧 ② 物理地址计算 - 物理地址表示 = (3, 6)

    物理地址 = 2^s*f + o
       
    F = 7   S = 9    f = 3  o = 6
    

    ③ 实际物理地址 = 2^9 * 3 = 6 = 1536 + 6 = 1542

  2. 页(Page)

    • 进程逻辑地址空间被划分为大小相等的页
    • 页内偏移 = 帧内偏移
    • 通常: 页号大小 != 帧号大小

    进程逻辑地址的表示: 二元组(P, O)

    P – 页号(P位, 2^p个页) O – 页内偏移(S位,每页有2^字节)

    虚拟地址 = P * 2^s + O

frame_f_o
page_frame_i

四,页表

1, 页表概述

  1. 每个进程都有一个页表
  2. 每个页面对应一个页表项
  3. 随进程运行状态而动态变化
  4. 页表基址寄存器(PTBR: Page Table Base Register)

页表项组成

帧号:f

页表项标志

  • 存在位(resident bit)
  • 修改位(dirty bit)
  • 引用位(clock/reference bit)

页式存储管理机制的性能问题

  1. 内存访问性能问题
    • 访问一个内存单元需要2次内存访问
    • 第一次访问:获取页表项
    • 第二次访问:访问数据
  2. 页表大小问题:
    • 页表可能非常大
    • 64位机器如果每页1024字节,那么一个页表的大小会是多少?
  3. 如何处理?

    • 缓存(Caching)
    • 间接(Indirection)访问

2, 快表(Translation Look-aside Buffer, TLB)

  1. 缓存近期服务的页表项
    • TLB使用关联存储(associative memory)实现,具备快速服务性能
    • 如果TLB命中,物理页号可以很快被获取
    • 如果TLB未命中,对应的表项被更新到TLB中

    translation_look_aside_buffer

3, 多级页表

  1. 通过间接引用将页号分成k级
    • 建立页表”树”
    • 减少每级页表的长度

    page_tree_

page_tree_instanl

4, 反置页表

大地址空间问题

  1. 对于大地址空间 (64-bits)系统,多级页表变得繁琐
    • 比如:5级页表
    • 逻辑(虚拟)地址空间增长速度快于网络地址空间
  2. 页寄存器和反置页面的思路

    • 不让页表与逻辑地址空间的大小相对应
    • 让页表与物理地址空间的大小相对应
  3. 页寄存器(Page Registers)

  4. 每个帧与一个页寄存器(Page Register)关联,寄存器内容包括:
    • 占用页号(Occupier): 对应的页号p
    • 使用位(Residence bit): 此帧是否被进程占用
      • 保护位(Protection bits)
  5. 页寄存器示例
    • 物理内存大小: 40964096=4K4KB=16 MB
    • 页面大小: 4096 bytes = 4KB
    • 页帧数: 4096 = 4K
    • 页寄存器使用的空间 (假设每个页寄存器占8字节):
    • 8*4096=32 Kbytes
    • 页寄存器带来的额外开销:32K/16M = 0.2% (大约)
    • 虚拟内存的大小: 任意
  6. 页寄存器方案的特征

优点:

  • 页表大小相对于物理内存而言很小
  • 页表大小与逻辑地址空间大小无关 缺点:
  • 页表信息对调后,需要依据帧号可找页号
  • 在页寄存器中搜索逻辑地址中的页号
  1. 页寄存器中的地址转换

  2. CPU生成的逻辑地址如何找对应的物理地址?
    • 对逻辑地址进行Hash映射,以减少搜索范围
    • 需要解决可能的冲突
  3. 用快表缓存页表项后的页寄存器搜索步骤
    • 对逻辑地址进行Hash变换
    • 在快表中查找对应页表项
    • 有冲突时遍历冲突项链表
    • 查找失败时,产生异常
  4. 快表的限制
    • 快表的容量限制
    • 快表的功耗限制(StrongARM上快表功耗占27%)
  5. 反置页表
  6. 基于Hash映射值查找对应页表项中的帧号
    • 进程标识与页号的Hash值可能有冲突
    • 页表项中包括保护位、修改位、访问位和存在位等标识

ptbr_hash_pid
page_hash_index

五,段页式存储管理

1, 段页式存储管理的需求

  1. 段式存储在内存保护方面有优势,页式存储在内存利用和优化转移到后备存储方面有优势。

  2. 段式存储、页式存储能否结合?

2, 段页式存储管理

在段式存储管理基础上,给每个段加一级页表

input_page_mgr

3, 段页式存储管理中的内存共享

通过指向相同的页表基址,实现进程间的段共享

page_mgr_mem

结语