Mr Dk.'s BlogMr Dk.'s Blog
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🐧 Linux Kernel Comments
    • Chapter 2 - 微型计算机组成结构

      • Chapter 2 - 微型计算机组成结构
    • Chapter 3 - 内核编程语言和环境

      • Chapter 3 - 内核编程语言和环境
    • Chapter 4 - 80X86 保护模式及其编程

      • Chapter 4.1-4.2 - 80X86 系统寄存器和系统指令 & 保护模式内存管理
      • Chapter 4.3 - 分段机制
      • Chapter 4.4 - 分页机制
      • Chapter 4.5 - 保护
      • Chapter 4.6 - 中断和异常处理
      • Chapter 4.7 - 任务管理
      • Chapter 4.8 - 保护模式编程初始化
      • Chapter 4.9 - 一个简单的多任务内核实例
    • Chapter 5 - Linux 内核体系结构

      • Chapter 5.1-5.2 - Linux 内核模式 & 体系结构
      • Chapter 5.3 - Linux 内核对内存的管理和使用
      • Chapter 5.4-5.6 - 中断机制 & 系统调用 & 系统时间和定时
      • Chapter 5.7-5.9 - Linux 进程控制 & 堆栈使用 & 文件系统
    • Chapter 6 - 引导启动程序 (boot)

      • Chapter 6 - 引导启动程序 (boot)
    • Chapter 7 - 初始化程序 (init)

      • Chapter 7 - 初始化程序 (init)
    • Chapter 8 - 内核代码

      • Chapter 8.1 - 内核代码总体功能
      • Chapter 8.2 - asm.s 程序
      • Chapter 8.3 - traps.c 程序
      • Chapter 8.4 - sys_call.s 程序
      • Chapter 8.5 - mktime.c 程序
      • Chapter 8.6 - sched.c 程序
      • Chapter 8.7 - signal.c 程序
      • Chapter 8.8 - exit.c 程序
      • Chapter 8.9 - fork.c 程序
      • Chapter 8.10 - sys.c 程序
    • Chapter 9 - 块设备驱动程序

      • Chapter 9.1 - 块设备驱动程序 总体功能
      • Chapter 9.2 - blk.h 文件
      • Chapter 9.3 - hd.c 程序
      • Chapter 9.4 - ll_rw_blk.c 程序
      • Chapter 9.5 - ramdisk.c 程序
    • Chapter 10 - 字符设备驱动程序

      • Chapter 10.1 - 字符设备驱动程序 总体功能
      • Chapter 10.2 - keyboard.S 程序
      • Chapter 10.3 - console.c 程序
      • Chapter 10.4 - serial.c 程序
      • Chapter 10.5 - rs_io.s 程序
      • Chapter 10.6 - tty_io.c 程序
      • Chapter 10.7 - tty_ioctl.c 程序
    • Chapter 12 - 文件系统

      • Chapter 12.1 - 文件系统 总体功能
      • Chapter 12.2 - buffer.c 程序
      • Chapter 12.3 - bitmap.c 程序
      • Chapter 12.4 - truncate.c 程序
      • Chapter 12.5 - inode.c 程序
      • Chapter 12.6 - super.c 程序
      • Chapter 12.7 - namei.c 程序
      • Chapter 12.9 - block_dev.c 程序
      • Chapter 12.10 - file_dev.c 程序
      • Chapter 12.11 - pipe.c 程序
      • Chapter 12.12 - char_dev.c 程序
      • Chapter 12.13 - read_write.c 程序
      • Chapter 12.14 - open.c 程序
      • Chapter 12.15 - exec.c 程序
      • Chapter 12.16 - stat.c 程序
      • Chapter 12.17 - fcntl.c 程序
      • Chapter 12.18 - ioctl.c 程序
      • Chapter 12.19 - select.c 程序

Chapter 4.4 - 分页机制

Created by : Mr Dk.

2019 / 07 / 25 11:45

Nanjing, Jiangsu, China


4.4 分页机制

80X86 内存管理机制的第二部分:负责将线性地址转换为物理地址。线性地址空间中的页面被映射到物理地址空间的页面上。设置 CR0 的 PG 位以启用分页机制,分页机制对 固定大小 的内存块进行操作。分页机制将线性地址空间和物理地址空间划分成页面,任何线性地址空间中的页都可以映射到任何物理地址空间中的页上。

80X86 使用 2^12 (4KB) 大小的固定页面,并对齐于 4K 地址边界。也就是说,4G 线性地址空间被划分为 2^20 (1M) 个页面。由于页对齐,线性地址空间的高 20-bit 被转换为物理地址空间的高 20-bit,低 12-bit 被直接用作页内偏移量。

地址转换机制允许一个线性地址被标注为无效的:

  1. OS 不支持的线性地址,产生无效地址的程序应当被终止
  2. 对应的页面在磁盘上,不在物理内存中,触发 OS 的异常,请求 OS 将对应页面从磁盘上载入物理内存

页错误异常:由页错误异常的处理程序让 OS 将相应页面载入内存。此过程中,OS 可能还需要将被替换的页面保存到磁盘上。页被载入物理内存后,异常返回操作会使得导致异常的指令被重新执行。用于 线性地址 → 物理地址 和 产生页错误异常 的信息保存在 页目录 和 页表 中

分页使用了固定长度的页面。因此,一个数据结构可以一部分存在于物理内存中,一部分存在于磁盘中。为了减少地址转换需要的总线周期,最近被访问的页目录和页表都会被放在 TLB 中 - 满足大多数读取页目录和页表的需求,无需使用总线周期。

4.4.1 页表结构

Page Table - 存放于物理地址空间中。可以看作是具有 2^20 个项的数组,映射功能即数组查找。由于页面基地址对齐于 4K 地址边界,低 12-bit 肯定是 0。

页表中每个页表项的大小为 32-bit (4B)其中只需要 20-bit 来存储物理页基地址,剩下 12-bit 可用于存放页属性信息。

4.4.1.1 两级页表结构

页表含有 1M 个表项,每个项 4B,共需要 4MB 的空间。为了减少内存占用量,80X86 使用了两级表,高 20-bit 的线性地址转换被分为两步,每步使用 10-bit。

第一级:页目录 (Page Directory),存放在一个 4KB 的页中,具有 2^10 (1K) 个 4B 的页目录项。页目录项中存放对应页表的页的 20-bit 物理基地址,线性地址的最高 10-bit 用于在页目录中进行查找。

第二级:页表 (Page Table),长度也是一个页,最多含有 1K 个 4B 的页表项。表项中存放对应页面的 20-bit 物理基地址,线性地址的中间 10-bit 用于在页面中进行查找。

查找到的 20-bit 物理基地址 + 线性地址低 12-bit 的页内偏移组成 32-bit 物理地址。其中,CR3 寄存器存放了页目录表的物理基地址。

4.4.1.2 不存在的页表

二级表结构允许页表被分散在内存各个页面中,不需要保存在连续的 4MB 空间中。而页目录表的页面必须总是存在于物理内存中。二级页表可以在需要时再分配。

页目录表和页表中每项的低 12-bit 有一个存在 (present) 属性,指明对应访问的页是否存在于物理内存。若不存在,则产生异常,令 OS 将页调入内存。因此,任何时候只需要部分二级页表存放在内存中即可,其余可保存在磁盘上。

4.4.2 页表项格式

每个页表项为 32-bit

  • 高 20-bit 为对应页面的物理基地址
  • 低 12-bit 为页属性信息
    • P - Present - 页存在位
    • R/W - Read/Write - 页面是否可被读写或执行
    • U/S - User/Supervisor - 页面特权级
    • A - Accessed - 页面是否被访问
      • CPU 只负责设置该标志
      • OS 可定期复位该标志来统计页面使用
    • D - Dirty - 处理器是否对页面进行了修改
    • AVL - 专供使用,处理器不会修改

4.4.3 虚拟存储

页表和页目录表的 P 标志为虚拟存储提供了必要的支持,已访问标志 A 和已修改标志 D 可以用于有效实现虚拟存储技术。周期性检查和复位所有的 A 标志,能够确定哪些页面最近没有被访问,这些页面会成为被替换到磁盘上的候选者。如果移出页面到磁盘时 D 标志位 0,说明该页没有被修改过,则说明磁盘上该页的副本与内存一致,无需写回磁盘。

Edit this page on GitHub
Prev
Chapter 4.3 - 分段机制
Next
Chapter 4.5 - 保护