【计算机组成原理】页表结构(虚拟内存的映射)

news2024/9/26 3:30:24

页表结构

  • 引言
  • 简单页表
  • 多级页表
  • 总结

引言

我们的指令和数据,都必须先加载到内存,才会被CPU拿去执行。但是程序并不能直接访问到物理内存。从这里可以知道,程序是怎么装载到内存中执行的。
0
我们的内存需要被分成固定大小的页(Page),然后才通过虚拟内存地址到物理内存地址的地址转换,才能到达实际存放数据的物理内存位置。而我们的程序看到的内存地址,都是虚拟内存地址。

那么,这些虚拟内存地址究竟是怎么转换成物理地址的呢?

内存保护的主要目的是防止某个进程去访问不是操作系统配置给它的寻址空间

简单页表

简答页表
想要把虚拟内存地址,映射到物理内存地址,最直观的方法,就是来键一张映射表。这个映射表,能够实现虚拟内存里面的页,到物理内存里面的页的一一映射。这会映射表,在计算机里面,就叫做页表(page table)

页表这个地址转换的办法,会把一个内存地址分成页号(Directory)和偏移量(Offset)两个部分。以一个32位的内存地址为例:

  1. 前面的高位,就是内存地址的页号,后面的低位,就是内存地址的偏移量

  2. 做地址转换的页表,只需要保留虚拟内存地址的页号和物理内存地址的页号之间的映射关系就可以了。

  3. 同一个页里面的内存,在物理层面是连续的
    01
    总结一下,对于一个内存地址转换,其实就是这样三个步骤:

  4. 把虚拟内存地址,切分成页号和偏移量的组合;

  5. 从页表里面,查询出虚拟页号,对应的物理页号;

  6. 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址

03
03

04
这还只是 32 位的内存地址空间,现在大家用的内存,多半已经超过了 4GB,也已经用上了 64 位的计算机和操作系统。这样的话,用上面这个数组的数据结构来保存页面,内存占用就更大了。那么,我们有没有什么更好的解决办法呢?

多级页表

仔细想一想,我们其实没有必要存下这 2^20 个物理页表啊。大部分进程所占用的内存是有限的,需要的页也自然是有限的,我们只需要去存那些用到的页之间的映射关系就好了。

也就引入了多级页表(Multi-Level Page Table)。那为什么不用哈希表呢?

(哈希表有哈希冲突,而且顺序乱,不符合局部性原理)

我们先来看一看,一个进程的内存地址空间是怎么分配的。在整个进程的内存地址空间,通常是“两头实,中间空”。在程序运行的时候,内存地址从顶部往下,不断分配占用的栈的空间。而堆的空间,内存地址则是从底部往上,是不断分配占用的。

所以,在一个实际的程序地址里面,虚拟内存占用的地址空间,通常是两端连续的空间。而不是完全随机的内存地址。而多级页表,就特别适合这样的内存地址分布。

我们以一个4级的多级页表为例,来看一下,同样一个虚拟内存地址,偏移量的部分和上面简单页表一样不变,但是原先的页号部分,我们把它拆成四段,从高到低,分成 4 级到1 级这样 4 个页表索引。

在这里插入图片描述
对应的,一个进程会有一个 4 级页表。我们先通过 4 级页表索引,找到 4 级页表里面对应的条目(Entry)。这个条目里存放的是一张 3 级页表所在的位置。4 级页面里面的每一个条目,都对应着一张 3 级页表,所以我们可能有多张 3 级页表。

找到对应这张 3 级页表之后,我们用 3 级索引去找到对应的 3 级索引的条目。3 级索引的条目再会指向一个 2 级页表。同样的,2 级页表里我们可以用 2 级索引指向一个 1 级页表。

而最后一层的 1 级页表里面的条目,对应的数据内容就是物理页号了。在拿到了物理页号之后,我们同样可以用“页号 + 偏移量”的方式,来获取最终的物理内存地址。

我们可能有很多张 1 级页表、2 级页表,乃至 3 级页表。但是,因为实际的虚拟内存空间通常是连续的,我们很可能只需要很少的 2 级页表,甚至只需要 1 张 3 级页表就够了

事实上,多级页表就像一个多叉树的数据结构,所以我们常常称它为页表树。因为虚拟内存地址分布的连续性,树的第一层节点的指针,很多就是空的,也就是不需要有对应的子树了。所谓不需要子树,其实就是不需要对应的 2 级、3 级的页表。找到最终的物理页号,就好像通过一个特定的访问路径,走到树最底层的叶子节点。

在这里插入图片描述
以这样的分成 4 级的多级页表来看,每一级如果都用 5 个比特表示。那么每一张某 1 级的页表,只需要 2^5=32 个条目。如果每个条目还是 4 个字节,那么一共需要 128 个字节。而一个 1 级索引表,对应 32 个 4KiB 的也就是 16KB 的大小。一个填满的 2 级索引表,对应的就是 32 个 1 级索引表,也就是 512KB 的大小。

我们可以一起来测算一下,一个进程如果占用了 1MB 的内存空间,分成了 2 个 512KB 的连续空间。那么,它一共需要 2 个独立的、填满的 2 级索引表,也就意味着 64 个 1 级索引表,2 个独立的 3 级索引表,1 个 4 级索引表。一共需要 69 个索引表,每个 128 字节,大概就是 9KB 的空间。比起 4MB 来说,只有差不多 1/500。

不过,多级页表虽然节约了我们的存储空间,却带来了时间上的开销,所以它其实是一个“时间换空间”的策略。原本我们进行一次地址转换,只需要访问一次就能找到物理内存地址。但是,用了4级页表,我们就需要访问4次内存,才能找到物理页号了。

问题是:内存访问其实比Cache要慢很多。我们本来只是要做一个简单的物理地址转换,现在却要多了访问多次内存。对于这个时间性能的损失,有什么好的办法吗?

总结

多级页表就像一棵树,因为一个进程的内存地址相对集中和连续,所以采用这种页表树的方式,可以大大节省页所需要的空间。而因为每一个进程都需要一个独立的页表,这个空间的节省是非常客观的
在优化页表的过程中,我们可以观察到,数组这样紧凑的数据结构,以及树这样稀疏的数据结构,在时间复杂度和空间复杂度的差异。另外,纯粹理论软件的数据结构和硬件的设计也是高度相关的。
转载自: 点击跳转

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

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

相关文章

docker部署Nacos2获取动态配置的失败的坑

Nacos2获取动态配置的失败的坑在此记录 nacos:2.0 依赖也引入了,配置也正确配置了,该写的注解也写了但是报错 [Nacos Config] config[dataIdxxx.yml, groupDEFAULT_GROUP] is empty 原因: nacos官网解释 给nacos容器增加额外两个…

Spring之IoC源码分析及设计思想(一)——BeanFactory

关于Spring的IOC Spring 是一个开源的 Java 平台,它提供了一种简化应用程序开发的框架。它是一个分层的框架,包括两个主要的内核:控制反转(IOC)和面向切面编程(AOP)。IOC 允许应用程序将组件之…

【计算机视觉中的 GAN 】如何稳定GAN训练(3)

一、说明 在上一篇文章中,我们达到了理解未配对图像到图像翻译的地步。尽管如此,在实现自己的超酷深度GAN模型之前,您必须了解一些非常重要的概念。如本文所提的GAN模型新成员的引入:Wasserstein distance,boundary eq…

解读分布式锁(redis实现方案)

1.导读 分布式锁是一种用于分布式系统中的并发控制机制,它用于确保在多个节点或多个进程之间的并发操作中,某些关键资源或代码块只能被一个节点或进程同时访问。分布式锁的目的是避免多个节点同时修改共享资源而导致的数据不一致或冲突的问题。通俗的来…

内网穿透技术 - 带你玩转NATAPP

前言 使用内网穿透工具,我们就可以在公网中直接访问在局域网内搭建的服务器网页,也可以直接远程连接到局域网内的机器。本文章主要介绍下NATAPP内网穿透工具的使用。 NATAPP使用教程 官网 在官网先注册,然后登录。登录后,会有一…

【弹力设计篇】弹力设计总结

前面主要聊了多个弹力设计,遮盖力主要做一个汇总 弹力设计总图 集群:服务不能是单点的,所以我们的架构需要冗余设计,设计成集群服务,也就是多个副本机制。需要具体的技术 负载均衡服务健康检查,使用像Ng…

飞桨AI Studio可以玩多模态了?MiniGPT4实战演练!

MiniGPT4是基于GPT3的改进版本,它的参数量比GPT3少了一个数量级,但是在多项自然语言处理任务上的表现却不逊于GPT3。项目作者以MiniGPT4-7B作为实战演练项目。 创作者:衍哲 一键fork fork该项目并运行,运行环境建议至少选择A100(4…

25.9 matlab里面的10中优化方法介绍—— 惩罚函数法求约束最优化问题(matlab程序)

1.简述 一、算法原理 1、问题引入 之前我们了解过的算法大部分都是无约束优化问题,其算法有:黄金分割法,牛顿法,拟牛顿法,共轭梯度法,单纯性法等。但在实际工程问题中,大多数优化问题都属于有约…

低代码PAAS平台源码,点击鼠标,就可以创建功能强大的企业应用程序,实现业务流程自动化

低代码PAAS平台采用对象方式实现字段、API的字段类型,引入RPA实现表自动化建模;再使用选择方式对地段功能进行选择定义甚至可以插入代码进行自定义。采用前后端同一技术,可实现功能应用边使用边修改的功能。 低代码PAAS平台,一套…

【100天精通python】Day15:python模块_第三方模块和包,模块如何以主程序形式执行

目录 1 常用的第三方模块 2. 第三方模块的安装和使用 2.1 安装第三方模块: 2.2 导入第三方模块: 2.3 使用第三方模块: 3 模块以主程序形式执行 4 python 中的包 4.1 python程序的包结构 4.2 创建包 4.3 python中包的导入和使用 5 …

redis 存储原理与数据模型

文章目录 一、redis的存储结构1.1 存储结构1.2 存储转换 二、字典(dict)实现2.1 数据结构2.2 哈希冲突2.3 扩容2.4 缩容2.5 渐进式rehash2.6 scan 命令2.7 expire机制 三、跳表(skiplist)实现3.1 理想跳表3.2 redis跳表 一、redis的存储结构 1.1 存储结构 1.2 存储转换 二、字…

Flowable-中间事件-信号中间抛出事件

定义 当流程执行到达信号抛出事件时,流程引擎会直接抛出信号,其他引用了与其相同的信号捕获 事件会被触发,信号发出后事件结束,流程沿后继路线继续执行。其抛出的信号可以被信号开始事 件(Signal Start Event&#xf…

vuejs源码阅读之优化器

前面讲过vuejs中解析器是把html模版解析成AST,而优化器的作用是在AST中找到静态子树并打上标记。 静态子树是指的那些在AST中永远不会发生变化的节点。 例如,一个纯文本节点就是静态子树,而带变量的文本节点就不是静态子树,因为…

VSCode配置之C++ SQLite3极简配置方案

背景 最近在学习《深入应用C11: 代码优化与工程级应用》,其中第13章说到SQLite库,查询网上诸多教程,发现比较容易出现bug且配置较为麻烦,故记录此次简化版方案,以供参考。 软件环境 SQLite 3.42.0 版本(仅…

基于Rsoft软件的达曼光栅仿真

1、概述 达曼光栅(Dammann grating,DG)是一种典型的二元光学元件(bianry optical elements,BOE),通过二元光学相位变化点的横向位置的调制来实现激光远场多级谱点等强度的光点阵列。 达曼光栅作为一种常用…

ReID网络:MGN网络(1) - 概述

Start MGN 1. 序言 现代基于感知的信息中,视觉信息占了80~85%。基于视觉信息的处理和分析被应用到诸如安防、电力、汽车等领域。 以安防市场为例,早在2017年,行业咨询公司IHS Market,我国在公共和私人领域安装有摄像头约1.76亿…

flask处理文件上传

flask处理文件上传 在Flask框架中,你可以使用request.files对象来处理文件上传。以下是一个简单的文件上传的示例: from flask import Flask, request from werkzeug.utils import secure_filename import osapp Flask(__name__)# 定义文件上传的路径…

二进制的妙用:判别2的幂次方的3把钥匙

本篇博客会讲解力扣“231. 2 的幂”的解题思路,这是题目链接。 这道题有3种巧妙的思路,且听我一一道来。 思路1 如果一个数是2的幂次方,则这个数的二进制中一定有且只有1位是1。比如,1的二进制是1,2的二进制是10&…

Python零基础入门(九)——函数,类和对象

系列文章目录 个人简介:机电专业在读研究生,CSDN内容合伙人,博主个人首页 Python入门专栏:《Python入门》欢迎阅读,一起进步!🌟🌟🌟 码字不易,如果觉得文章不…

Spring 6【方法参数校验、SpingAOP介绍、Schema-based方式实现AOP 】(十四)-全面详解(学习总结---从入门到深化)

目录 4.方法参数校验 SpingAOP介绍 Schema-based方式实现AOP 4.方法参数校验 Spring框架提供了一种校验方法参数的方法,在调用一个方法传入参数后,会判断参数是否满足数据校验。如果满足方法执行,如果不满足:不执行方法&…