进程地址空间 页表

解释虚拟地址和写实拷贝的数据解耦问题

结构

  • 对于每个进程的内核PCB结构来说,其中都存储了进程地址空间结构的地址

什么叫进程地址空间?

  • 进程地址空间,本质上是一个描述进程可用地址范围的大小。

  • 进程地址空间存储着进程运行时所需要的数据的虚拟地址。经过页表映射才能访问到物理地址

进程地址空间的作用

  • 避免将所有数据直接记录到物理内存中,方便管理,让我们以统一结构的视角看待内存,即在虚拟内存中各个空间对应的地址有序固定,而实际映射的物理内存的位置并不固定

地址空间

进程地址空间的区域划分(mm_struct)

mm_struct的部分字段

  • 如上图所示,地址空间中存在各种各样的区域。我们通过记录每个区域的起始地址和结束地址,就可以将各个区域划分开来。

  • 如果超过了规定的值,就称为越界

页表

k-V

虚拟地址 物理地址 标志位 代码或者数据是否已经载入到内存
0x123 0x321 rw 1
  • rw:可读可写
  • 1:已经被加载

页表例图
例如:

  • CPU中,存在一个cr3寄存器(类似的还有cr2),存储着当前进程的页目录(物理地址),并且在进程切换的时候,页表的地址也会被现场保护

  • 根据记录的虚拟地址找到物理地址。

页表的作用

  • 权限管理——利用页表记录的标志位,可以检查内存操作是否违规
    例如:如果有一个变量位于常量区,那么它的标志位为r(只读),如果尝试w(写入)的时候,就会被阻拦。

  • 拦截越界如果在转换过程中内存出现了异常访问,直接进行拦截。从而这个请求不会抵达物理内存,从而保护物理内存。

页表的存储方式

假设现有一个地址 0000 0000 0000 0000 0000 0000 0000 0001,在32位的x86架构下,这个地址会被分为三段:

  1. 10位:对应一级页表(页目录)中的页目录表项(PDE)。
  2. 10位:对应二级页表(页表)中的页表项(PTE)。
  3. 12位:对应页框内的偏移量。

分段详细解释

  • 页目录表项(PDE):一级页表的10位用于索引页目录表项。页目录表项指向一个页表。
  • 页表项(PTE):二级页表的10位用于索引页表项。页表项指向一个物理页框。
  • 页框内的偏移量:最后的12位用于指定页框内的偏移量。一个页框的大小为4KB(2^12字节)。

页表的大小

一个进程中的页表大小的计算如下:

  • 每个页目录(一级页表)包含1024个页目录表项,每个页目录表项指向一个页表。
  • 每个页表(二级页表)包含1024个页表项,每个页表项指向一个物理页框。

由于每个页目录表项和页表项通常占用4字节:

  • 一个页目录的大小:1024 * 4 = 4096字节 = 4KB。
  • 一个页表的大小:1024 * 4 = 4096字节 = 4KB。

一个进程中的页表总大小:

  • 页目录的大小 + 页表的大小总和。
  • 在最坏情况下,假设每个页目录表项都指向一个页表,总共1024个页表,那么总大小为:
    • 页目录:4KB
    • 1024个页表:1024 * 4KB = 4MB

父子进程

  • 子进程在创建时,也会基于父进程创建属于自己的页表进程地址空间
    进程fork前后程序逻辑

写实拷贝–操作系统自动完成的

  1. 当子程序有对数据进行修改,并且通过页表访问到的物理地址和父进程的地址是同一个的时候。

  2. 就调整子进程的页表,将重新分配一块区域并记录到子程序的页表中。

(注意,这里没有修改虚拟地址,所以父子进程的虚拟地址还可能相同

惰性加载

运行一个程序时,并不会将它对应磁盘的数据都加入到内存中,而时分批加载

并且,如果短期内不会使用的数据,并不会被加载到内存 —— 惰性加载页表中会进行记录。

因此,我们在创建一个进程的时候,先创建内核数据结构,再加载对应的可执行程序

总结:

进程地址空间和页表,实现了进程管理模块内存管理模块的解耦


进程地址空间 页表
https://weihehe.top/2024/07/14/进程的地址空间/
作者
weihehe
发布于
2024年7月14日
许可协议