Linux | 从虚拟地址到物理地址

前言

本章主要讲解虚拟地址是怎么转化成物理地址的,以及页表相关知识;本文环境默认为32位机器下;如果你连什么是虚拟地址都不知道可以先看看下面这篇文章;

Linux | 进程地址空间-CSDN博客

一、概念补充

**页表:**是一种数据结构,与硬件MMU配合可以将虚拟地址转化成物理地址,页表中主要建立虚拟地址与物理地址之间的映射;

**页框:**我们将真实物理内存以4KB为单位进行划分,其中每一个4KB我们称为一个页框;

**页框号:**识别页框的编号;

知识回顾:

之前我们讲解磁盘文件时,我们说过,通常进行一次IO的大小通常为4KB,即使你只修改1字节也是以4KB为单位将数据先加载进内存中;实际上,也正是加载进内存的空闲页框中;我们的磁盘文件也是以4KB进行划分;

我们还说过我们的一个可执行程序在编译后形成可执行程序,这个可执行程序实际上已经在内部进行分段,分好了虚拟地址空间了;我们可以直接使用编译好的虚拟地址;

二、地址转化过程

前面我们说过我们的物理内存会以4KB分为一个又一个页框;而操作系统是否需要维护这些页框呢?答案当然也是肯定的,我们可以将我们的页框用一种结构体描述起来,然后用数组维护这些页框,这样就有一个页框数组了,数组下标可作为页框号;假设一个为4GB的物理内存,可以有多少个页框呢?我们不难计算,4GB = 4 * 1024 * 1024 * 1024 Byte;

一个页框为4KB = 4 * 1024;两者相除,大约就是1024*1024,约一百万个;我们便可以用

struct page[1000000]; 即可表示所有物理内存中所有页框;
首先我要讲解的是我们的虚拟地址通过页表+MMU将我们的虚拟地址转换成物理内存中的物理地址,若我们页表中没有物理内存中的地址,而是只有磁盘中的地址,此时是因为我们的数据没有被加载进磁盘,可能之前发生或换出或本来没有加载进磁盘内;这是我们在物理内存中申请一块空闲的页框,我们找到空闲的页框后,我们将磁盘文件加载进指定的页框,同时我们也在页表上进行更新,将新映射的物理内存地址填上去;这个过程也就是我们常说的缺页中断

如果按上面的结构来看,页表中的每个条目记录一个虚拟地址映射一个物理地址,此时我们一共则需要 4 * 1024 * 1024 * 1024条记录(假设物理内存有4G);假设一条记录需要10个字节,那么一个页表的大小就需要40G;而我们的页表也是存在物理内存中呀!这显然是不可能存的下的,就算存的下也不可能消耗这么多内存资源存页表,况且一个进程就有一张用户级页表;计算机中绝对不止有一个进程;

此时,我们用另一种思路,我们页表中将虚拟地址的32个比特位分开看;其中前10位我们一起看,作为页目录的索引来找到二级页表,然后接着10位用来查找页框号,最后12个比特位用来记录页内偏移;如下图所示;

我们来计算一下,页目录最多有2^10,也就是1024条目录,对应着最多有1024个二级页表;每个二级页表也最有有2^10条目录,每条目录对应一个页框号,所有二级页表可以表示2^10 * 2^10 个页框,而我们的4GB内存最多也只有 2^20 个页框,刚好一一对应;最后12个比特位可以表示0到2^12 - 1,而2^12正好也就是4KB;也正好吻合;设页表每一条目为10字节,计算最大的情况下,总大小为 页目录大小(2^10 * 10 = 10KB)+ 所有二级目录大小(2 ^ 10 * 2 ^ 10 * 10 = 10MB);其中10KB可忽略,总大小最多为10M;这个大小比我们第一种方案要小了很多很多,这也是我们Linux下采用的方案;

相关推荐
ybb_ymm3 分钟前
mysql8在linux下的默认规则修改
linux·运维·数据库·mysql
半梦半醒*5 分钟前
zabbix安装
linux·运维·前端·网络·zabbix
武文斌773 小时前
复习总结最终版:单片机
linux·单片机·嵌入式硬件·学习
驱动探索者3 小时前
贝尔实验室发展史:20世纪科技圣殿的辉煌与沉浮
linux
何朴尧3 小时前
centos/cuos如何开启软件源
linux·运维·centos
YouEmbedded4 小时前
解码Linux文件IO之标准IO
linux·文件io·系统io
撬动未来的支点4 小时前
【Linux内核】Linux内核裁剪完全指南:从理论到实战的系统优化
linux
csdn_Hzx4 小时前
Linux添加一个系统服务
linux·运维·服务器
洛克大航海5 小时前
Ubuntu安装Hbase
大数据·linux·数据库·ubuntu·hbase
赖small强5 小时前
Linux内存管理-缓存系统中的Major和Minor详解
linux·缓存·交换缓存机制·major fault·minor fault