【进程空间】通过页表寻址的过程

文章目录

  • 前言
  • 介绍页表、页框、页目录的概念
    • 页框
    • 页表
    • 页目录
    • 页表和页目录的分配
  • 一级页表和二级页表
    • 一级页表
      • 寻址过程
    • 二级页表
      • 寻址过程
    • 一级页表和二级页表的对比

前言

我们知道每个进程都有属于自己的虚拟地址空间,且每个进程的虚拟地址都是统一的。要想通过虚拟地址访问物理地址,我们就需要借助页表来建立映射关系。下面对于如何借助页表来寻址展开详细解释(以32位操作系统为例)。

介绍页表、页框、页目录的概念

页框

页框(Page Frame)是物理内存中的固定大小的块,通常为4KB。在物理内存中,页框是用于存储实际数据的最小单元。假设内存大小为4GB,也就能划分出1024*1024个页框。当进程通过页表来访问物理地址时,其本质就是找到页框的地址。

在这里插入图片描述
于是,操作系统对内存的管理,就可以看成是对页框即块的管理。那内核中又是如何描述一个页框的呢?
在Linux内核中,使用struct page结构来描述内存中的每一页框。这个结构体定义在内核头文件include/linux/mm_types.h中。该结构体通常有以下字段:

  • flags:标志位,表示页面的各种状态
  • mapping:指向该页框所属的地址空间
  • index:该页框在地址空间中的偏移量
  • _maocount:记录该页框到页表条目数
  • _refcount:页面引用计数。表示有多少用户正在使用该页框

页表

页表是用于存储物理内存与虚拟内存地址之间的映射关系的结构。每个进程都有属于自己的页表。页表中的每一个表项,都对应着一个页框的物理地址。一个页表项(PTE)通常包括以下几个字段:

  • 页框基地址:页框的第一个字节的地址
  • 控制位:包括存在位(P)、读/写位(R/W)、超级用户位(U/S)等。

给出32位页表项的控制位示例:
在这里插入图片描述
(上图来自知乎)

再给出内核中描述页表项的结构体代码,该结构体其实是一个位段,所有变量加起来一共32个bite位,即4字节:

// 页表项(PTE)的定义
typedef struct {uint32_t present    : 1;  // 存在位uint32_t rw         : 1;  // 读/写位uint32_t us         : 1;  // 用户/超级用户位uint32_t pwt        : 1;  // 页级写穿透位uint32_t pcd        : 1;  // 页级缓存禁用位uint32_t accessed   : 1;  // 访问位uint32_t dirty      : 1;  // 脏位uint32_t pat        : 1;  // 页属性表位uint32_t global     : 1;  // 全局位uint32_t available  : 3;  // 可用位uint32_t page_frame_base : 20; // 页框基地址
} __attribute__((packed)) page_table_entry_t;

页表其本质就是这种结构体数组

页目录

页目录是用来管理页表的结构。页目录中每一表项都指着一张页表的物理地址。一个页目录项(PDE)通常包括以下几个字段:

  • 页表基地址:页表的首地址(物理)
  • 控制位:包括存在位(P)、读/写位(R/W)、超级用户位(U/S)等。

给出32位页目录项的控制位示例:
在这里插入图片描述
(上图来着知乎)
同样,给出内核中描述页目录项的代码:

// 页目录项(PDE)的定义
typedef struct {uint32_t present    : 1;  // 存在位uint32_t rw         : 1;  // 读/写位uint32_t us         : 1;  // 用户/超级用户位uint32_t pwt        : 1;  // 页级写穿透位uint32_t pcd        : 1;  // 页级缓存禁用位uint32_t accessed   : 1;  // 访问位uint32_t reserved   : 1;  // 保留位uint32_t ps         : 1;  // 页大小(通常为4KB页)uint32_t ignored    : 1;  // 忽略位uint32_t available  : 3;  // 可用位uint32_t page_table_base : 20; // 页表基地址
} __attribute__((packed)) page_directory_entry_t;

综上,我们知道了页框、页表、页目录的概念,以及彼此之间的联系。那么在一个进程建立的时候, 页表和页目录的内容是固定的吗? 答案是否定的。

页表和页目录的分配

在Linux内核中,新进程的页目录表的内容是动态增加的。这意味着页目录表和页表的分配更新会根据实际情况动态进行,而不是在创建进程时一次初始化所有的页表项。
大致步骤如下:

  1. 进程创建建立并初始化新页目录表。该表大部分内容为空,有部分指向共享内核。
  2. 访问虚拟地址,如果该地址对应的页表项不存在,触发页故障。内核捕捉这个故障,然后给进程分配对于的页表,并更新页目录表页页表

一级页表和二级页表

在操作系统中,分页机制可以采用单级页表和多级页表进行地址映射。linux采用的就是多级页表。不同的分页机制会导致寻址的空间成本不同(页表本身也占空间)。下面以一级页表和二级页表为例,分析各自的空间成本。
单级页表:只有一张大的页表来映射虚拟空间和物理空间。结构较为简单,直接映射。
多级页表:分层次的管理地址空间,且一般都有一张页目录表。结构较为复杂,需要多次转换地址。

一级页表

总共就一张表。

  • 页表项大小:通常每一个页表项都是4个字节,即32个比特位。
  • 页表项数目:因为4GB内存一共有1024*1024个页框,要想映射所有页框。也就需要1024*1024个页表项。

一级页表的总大小:4bite10241024=4MB

当我们采用一级页表。给出一个虚拟地址(32位),如何找到目标的物理地址(某一字节)呢?

寻址过程

将虚拟地址分解为两个部分:

  1. 页表索引:高20位。因为一张页表的总项数为1024*1024=2^20(页框数),虚拟地址的高20位用来表示页表项的位置。
  2. 页内偏移量:低12位。通过高20位能找到一个唯一的页表项,即页框的物理地址。一个页框占4096个字节,用12位比特位恰好能表示4096个不同的位置。于是通过低12位比特位的组合,我们就能找到页框内的唯一一个字节。

假设现在有一个虚拟地址为:0x0000 1005取出高20位的十进制值为1,低12位的十进制值为5.于是在页表中找到下标为1的页表项,通过这个页表项我们能找到一个唯一的页框。再在该页框中从找到第5个字节的地址。该地址就是0x0000 1005对应的物理地址。
在这里插入图片描述

二级页表

在二级页表中,最外层的页表我们当成一个页目录。页目录中的每一项都指向一张页表。一共有1024个页目录项,即一共有1024张页表,每一张页表有1024个页表项,刚好对应1024*1024个页框。
1.页目录大小计算:

  • 页目录项大小:4字节。
  • 页目录数量:1024.

页目录总大小:4byte*1024=4KB

2.每个页表的大小计算:

  • 页表项大小:4字节
  • 页表项数量:每一个页表都有1024个页表项

每个页表的大小:10244byte=4KB
页表的总大小:1024
4KB=4MB
二级页表的总大小:4MB+4KB约等于4MB

寻址过程

将虚拟地址分为三个部分:

  1. 页目录索引:高10位用来索引页目录项,10个二进制位最多表示1024个位置。
  2. 页表索引:中间10位索引页表项
  3. 页内偏移量:低12位用于表示页内偏移量,12个二进制位最多表示4096个位置,刚好对应页框内每个字节的相对位置。

当我们拿到一个虚拟地址,取出高10位的二进制表示的值,作为页目录的下标找到目标页表。再取出中间10位二进制表示的值,用来作为目标页表的下标,来找到目标页框。最后取出低12位,在目标页框中找到唯一一个字节地址。

假设现在有一个虚拟地址0x00001005,得到页目录索引为0,页表索引为1,页内偏移量为5.所以我们就去下标为0的页目录项种去找到页表,并在该页表下标为1的页表项中找到页框,最后在该页框中找到第5个字节的地址。
在这里插入图片描述

一级页表和二级页表的对比

尽管从理论上看,一级页表和二级页表的总空间成本差不多。但是二级页表的使用效率会更高。
如果采用一级页表,每个进程都需要分配整个页表的内存,也就意味着每个进程都需要有4MB的空间来存放页表,且页表项很多都是空的。这对大多数应用来说都是一种浪费。

如果采用二级页表或者三级页表。每个进程拥有一张页目录页表的数量会根据实际情况来进行分配,因此实际内存小于4MB。这样一来,避免了为进程分配大量未使用的页表,从而节省了内存
从时间效率上来看,虽然一级页表直接可以找到页框的地址,而多级页表需要经过多次索引,但是多级页表带来空间上的节省是值得多消耗一些索引时间的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843356.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构(七)递归、快速排序

文章目录 一、递归(一)使用递归实现1~n求和1. 代码实现:2. 调用过程:3. 输出结果: (二)青蛙跳台阶问题1. 问题分析2. 代码实现3. 输出结果4. 代码效率优化5. 优化后的输出结果 二、快速排序&…

Euler 欧拉系统介绍

Euler 欧拉系统介绍 1 简介重要节点与版本EulerOS 特色EulerOS 与 openEuler 区别联系Euler 与 HarmonyOS 区别联系 2 openEuler特色支持 ARM,x86,RISC-V 等全部主流通用计算架构融入 AI 生态嵌入式实时能力提升引入 OpenHarmony 一些突出功能 参考 1 简…

将 KNX 接入 Home Assistant 之二 准备软件

写在前面: 在KNX官网也有关于 Home Assistant 的教程,地址是 Get started with Home Assistant x KNX 需要的东西是 a KNX IP Interface or Routera Raspberry Pian SD Card at least 32 GB 安装 Home Assistant 系统 下载镜像: 地址&…

idea中git检出失败

之前clone好好的,今天突然就拉取不下来了。很多时候是用户凭证的信息没更新的问题。由于window对同一个地址都存储了会话。如果是新的会话,必须要更新window下的凭证。 然后根据你的仓库找到你对应的账户,更新信息即可。

反射器和联邦实验

拓扑 要求 IP配置 [R1-GigabitEthernet0/0/0]ip add 12.0.0.1 24 [R1-LoopBack0]ip add 192.168.1.1 24 [R1-LoopBack1]ip add 10.0.0.1 24[R2-GigabitEthernet0/0/0]ip add 12.0.0.2 24 [R2-GigabitEthernet0/0/1]ip add 172.16.0.1 21 [R2-GigabitEthernet0/0/2]ip add 17…

(IDEA修改Java版本)java: 警告: 源发行版 X 需要目标发行版 X

搜索关键词:一致、发行 错误信息 其他错误: java: 错误: 不支持发行版本 6 java: -source 1.5 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式) 思路 有两个地方要检查,JDK版本保持一致即可。 比如统一用JDK8或…

FM1800隧道广播插播控制器

隧道广播插播控制器是一款群载波&应急广播插播控制器采用SDR软件无线电技术,产生独立的插播信号与“群载波”信号,本设备可通过软件无线电技术将音频信号调制成调频载波或“群载波”信号,分别送入插播主机,实现隧道广播远端机…

20240528解决飞凌的OK3588-C的核心板可以刷机不能连接ADB的问题

20240528解决飞凌的OK3588-C的核心板可以刷机不能连接ADB的问题 2024/5/28 16:34 OS:Linux R4/Buildroot 硬件接了3条线出来,一直可以刷机,但是链接ADB异常。 【总是链接不上】 Z:\OK3588_Linux_fs\kernel\arch\arm64\boot\dts\rockchip\OK3…

Android11 事件分发流程

在Android 11 输入系统之InputDispatcher和应用窗口建立联系一文中介绍到,当InputDispatcher写入数据后,客户端这边就会调用handleEvent方法接收数据 //frameworks\base\core\jni\android_view_InputEventReceiver.cpp int NativeInputEventReceiver::h…

炒黄金怎么追单?-融知财经网

在黄金投资领域,当市场行情呈现出有利的走势时,许多交易者会选择追加下单以扩大盈利。追单作为一种投资策略,旨在利用市场波动获取额外收益。然而,要想在追单中取得成功,需要掌握一定的技巧和策略。融知财经网给介绍黄金交易中追单的一些关键技巧,帮助投资者理智追单,稳健获利。…

线性插值的频域特性

1、抽取和插值的简单说明 抽取和插值是变采样过程中常用的两种手段,其中抽取的目的是降低数据的采样率,以降低对系统存储深度或计算量的要求。插值的目的是提高数据的采样率,以提高系统的计算精度。 M M M倍抽取通常是通过每隔 M M M…

Docker安装Nginx 并实现通过nginx部署静态网址

Docker镜像就是一个只读的模板,可以用来创建Docker容器。 例如:一个镜像可以包含一个完整的centos操作系统环境,里面仅安装了mysql、nginx等或用户需要的其他应用程序。 Docker提供了一个非常简单的机制来创建镜像或者更新现有的镜像&#…

GTD时间管理法

Part 1. What is GTD? | 什么是GTD? GTD is a framework that enhances focus and productivity. Through techniques such as capturing all tasks in a trusted system and breaking down complex projects into actionable items, GTD allows individuals to co…

美业系统SaaS收银系统源码-顾客在系统付款了但系统未显示怎么办?美业系统实测

美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 活动促销 PC管理后台、手机APP、iPad APP、微信小程序 1. 提供门店名称、付款凭证和会员手机号 2. 到订单明细查询, 按门店名称和会员手机号查询看是否有相…

百度智能云千帆AppBuilder升级!开放多源模型接入,思考模型再次加速!

>>【v0.5.4版本】 上线时间:2024/5/24 关键发版信息: 大模型优化:开放多源模型接入,思考模型再次加速! Agent思考模型:新增AppBuilder专用版模型ERNIE Speed-AppBuilder,自主任务规划…

【软考】下篇 第15章 面向服务架构设计理论与实践

目录 一、SOA定义二、微服务微服务优势微服务与SOA对比微服务架构模式方案微服务设计约束 三、SOA参考架构四、SOA设计的标准要求五、SOA设计原则六、SOA设计模式七、SOA实施 一、SOA定义 面向服务的体系结构 (Service-Oriented Architecture,SOA), 从应用和原理的角度看&…

openLayers加载wms图层并定位到该图层

openLayers定位到wms图层 我们的wms是加载geoserver发布的服务,wms加载的图层是没法通过layer.getSource().getExtent()来获取到extents(边界)的;实现思路是通过postgis的函数(st_extent(geom))来获取extents; 返回前端后格式化一…

23-LINUX--TCP连接状态

一.TCP服务的特点 传输层协议主要有两个:TCP 协议和 UDP协议。TCP 协议相对于UDP协议的特点是:面向连接、字节流和可靠传输。 使用TCP协议通信的双方必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源&a…

lammps案例:reaxff势模拟Fe(OH)3高温反应过程

大家好,我是小马老师。 本文分享一个reaxff反应势的案例。 该案例主要模拟Fe(OH)3在高温下的反应过程,主要代码来自lammps自带的案例。 lammps自带案例没有产物输出,故在此基础上稍加修改,增加了产物输出命令。 反应过程如下图…

JavaWeb开发 3.Web开发 Web前端开发 ③ HTML、CSS

没有一朵花,一开始就是一朵花 —— 24.5.28 HTML、CSS知识在博主前端专栏,可以对照博客大致进行了解 https://blog.csdn.net/m0_73983707/category_12654678.htmlhttps://blog.csdn.net/m0_73983707/category_12654678.html