【计组】内存和总线--《深入浅出计算机组成原理》(十)

news2024/11/17 4:24:35

 课程链接:深入浅出计算机组成原理_组成原理_计算机基础-极客时间 

一、虚拟内存和内存保护

日常使用的操作系统下,程序不能直接访问物理内存。内存需要被分成固定大小的页(Page),再通过虚拟内存地址(Virtual Address)到物理内存地址(Physical Address)的地址转换(Address Translation),才能到达实际存放数据的物理内存位置。而程序看到的内存地址,都是虚拟内存地址。

(一)简单页表

想要把虚拟内存地址映射到物理内存地址,最直观的办法就是来建一张映射表。这个映射表,能够实现虚拟内存里面的页到物理内存里面的页的一 一映射。这个映射表,在计算机里面,就叫作页表(Page Table)。页表会把一个内存地址分成页号(Directory)偏移量(Offset)两个部分。

做地址转换的页表,只需要保留虚拟内存地址的页号和物理内存地址的页号之间的映射关系就可以了。同一个页里面的内存,在物理层面是连续的。

对于一个内存地址转换,其实就是这样三个步骤:

  • 把虚拟内存地址,切分成页号和偏移量的组合;
  • 从页表里查询出虚拟页号对应的物理页号;
  • 拿物理页号加上前面的偏移量,得到物理内存地址。

 每一个进程,都有属于自己独立的虚拟内存地址空间,也就意味着,每一个进程都需要这样一个页表。 

(二)多级页表

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

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

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

对应的,一个进程会有一个 4 级页表。 4 级页表里面存放的是每张 3 级页表所在的位置。3级表指向二级表,二级表指向一级表。

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

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

大部分进程所占用的内存是有限的,需要的页也自然是很有限的,只需要去存那些用到的页之间的映射关系就好了。

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

二、解析TLB和内存保护

(一)加速地址转换:TLB

机器指令里面的内存地址都是虚拟内存地址。程序里面的每一个进程,都有一个属于自己的虚拟内存地址空间。可以通过地址转换来获得最终的实际物理地址。每一个指令和数据都存放在内存里面因此,“地址转换”是一个非常高频的动作,“地址转换”的性能至关重要。

从虚拟内存地址到物理内存地址的转换通过页表来处理。为了节约页表的内存存储空间,我们会使用多级页表数据结构。这就需要多次访问内存,然而,内存访问比 Cache 要慢很多,为了提高性能,可以采用加个"加个缓存"的方法。

程序使用的指令,存放和执行都是顺序进行的。也就是说,对于指令地址的访问,存在“空间局部性”和“时间局部性”,而需要访问的数据也是一样的。连续执行的几条指令通常存放在同一个"虚拟页"里,转换的结果自然也就是同一个物理页号。那就可以用“加个缓存”的办法把之前的内存转换地址缓存下来。这样就不用反复去访问内存来进行内存地址转换了。

于是,计算机工程师们专门在 CPU 里放了一块缓存芯片。这块缓存芯片我们称之为 TLB,全称是地址变换高速缓冲(Translation-Lookaside Buffer)。这块缓存存放了之前已经进行过地址转换的查询结果。这样,当同样的虚拟地址需要进行地址转换的时候,就可以直接在 TLB 里面查询结果了。

TLB 和我们前面讲的 CPU 的高速缓存类似,可以分成指令的 TLB 和数据的 TLB,也就是 ITLBDTLB。同样的,也可以根据大小对它进行分级,变成 L1、L2 这样多层的 TLB。

除此之外,和 CPU 里的高速缓存一样,它也需要用脏标记这样的标记位,来实现“写回”缓存管理策略。

为了性能,整个内存转换过程都由硬件来执行。 CPU 芯片里封装了内存管理单元(MMU,Memory Management Unit)芯片,用来完成地址转换。和 TLB 的访问和交互,都是由这个 MMU 控制的。

(二)安全性与内存保护

指令、数据都存放在内存里,如果被人修改了内存里的内容, CPU 就可能会去执行计划之外的指令。这个指令可能是破坏服务器里面的数据,也可能是被人获取到服务器里面的敏感信息。

虽然现代的操作系统和 CPU已经做了各种权限的管控。正常情况下,已经通过虚拟内存地址和物理内存地址的区分,隔离了各个进程。但是难免还是存在一些漏洞。在对于内存的管理里面,计算机有一些最底层的安全保护机制。这些机制统称为内存保护(Memory Protection)。

内存层面的安全保护核心策略,是在可能有漏洞的情况下进行安全预防

1、可执行空间保护

可执行空间保护(Executable Space Protection)是说,对于一个进程使用的内存,只把其中指令部分设置成“可执行”的,对于其他部分,比如数据部分,不给予“可执行”的权限。因为无论是指令,还是数据,在 CPU 看来,都是二进制的数据,直接把数据部分拿给 CPU,如果这些数据解码后,也能变成一条合理的指令,那也是可执行的。

对进程里内存空间的执行权限进行控制,可以使得 CPU 只能执行指令区域的代码。对于数据区域的内容,即使找到了其他漏洞想要加载成指令来执行,也会因为没有权限而被阻挡掉。

2、地址空间布局随机化

地址空间布局随机化(Address Space Layout Randomization)。原先一个进程的内存布局空间是固定的,所以第三方很容易知道指令在哪里,程序栈在哪里,数据在哪里,堆又在哪里。而地址空间布局随机化这个机制,就是让这些区域的位置不再固定,在内存空间随机去分配这些进程里不同部分所在的内存空间地址,让破坏者猜不出来。猜不出来呢,就没法找到想要修改的内容的位置。如果只是随便做点修改,程序只会 crash 掉,而不会去执行计划之外的代码。

三、总线

(一)总线的设计思路

计算机里其实有很多不同的硬件设备,除了 CPU 和内存之外,还有大量的输入输出设备。可以说,计算机上的每一个接口,键盘、鼠标、显示器、硬盘,乃至通过 USB 接口连接的各种外部设备,都对应了一个设备或者模块。

如果各个设备间的通信,都是单独进行的,每一个设备或者功能电路模块,都要和其他 N−1 个设备去通信,那么, N 个不同的设备,系统复杂度就会变成   。总线是为了简化复杂度而引入的,它把   的复杂度,变成了 N 。

对应的设计思路,在软件开发中也是非常常见的,譬如事件总线(Event Bus)的设计模式。

【延申阅读】设计模式:事件总线 - DZone

在事件总线这个设计模式里,各个模块触发对应的事件,并把事件对象发送到总线上。也就是说,每个模块都是一个发布者(Publisher)。而各个模块也会把自己注册到总线上,去监听总线上的事件,并根据事件的对象类型或者是对象内容,来决定自己是否要进行特定的处理或者响应。

这样的设计下,注册在总线上的各个模块就是松耦合的。模块互相之间并没有依赖关系。无论代码的维护,还是未来的扩展,都会很方便。

(二)三种线路和多总线架构

现代的 Intel CPU 的体系结构里面,通常有好几条总线。

首先,CPU 和内存以及高速缓存通信的总线,这里面通常有两种总线。这种方式,叫作双独立总线(Dual Independent Bus,缩写为 DIB)。CPU 里,有一个高速的本地总线(Local Bus),也叫后端总线(Back-side Bus),是用来和高速缓存通信的;还有一个速度相对较慢的前端总线(Front-side Bus),处理器总线(Processor Bus)、内存总线(Memory Bus),是用来和主内存以及输入输出设备通信的。

前端总线其实就是系统总线。CPU 里面的内存接口,直接和系统总线通信,然后系统总线再接入一个 I/O 桥接器(I/O Bridge)。 I/O 桥接器的另一边接入内存总线,使CPU 和内存通信。

在物理层面,其实完全可以把总线看作一组“电线”。这些电线之间是有分工的,通常有三类线路:

  • 数据线(Data Bus),用来传输实际的数据信息。
  • 地址线(Address Bus),用来确定到底把数据传输到哪里去,是内存的某个位置,还是某一个 I/O 设备。
  • 控制线(Control Bus),用来控制对于总线的访问。

总线减少了设备之间的耦合,也降低了系统设计的复杂度,但同时也带来了一个新问题,那就是总线不能同时给多个设备提供通信功能。

 课程链接:深入浅出计算机组成原理_组成原理_计算机基础-极客时间 

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

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

相关文章

卡通形象人物2 写代码-睡觉 丝滑如德芙

目录 本次实现效果 目录结构 index static/css/style.css static/js/script.js 结语: 前期回顾 【 css动画 】—— 把你喜欢css动画嵌入到浏览器中_0.活在风浪里的博客-CSDN博客常用酷炫动画999合集,代码直接复制可用,总用你想找的…

【Java】 JAVA Notes

JAVA语言帮助笔记Java的安装与JDKJava命名规范JAVA的数据类型自动类型转换强制类型转换JAVA的运算符取余运算结果的符号逻辑运算的短路运算三元运算符运算符优先级JAVA的流程控制分支结构JAVA类Scanner类Math 类random方法获取随机数Java的安装与JDK JDK安装网站:h…

AXI 总线协议学习笔记(4)

引言 前面两篇博文从简单介绍的角度说明了 AXI协议规范。 AXI 总线协议学习笔记(2) AXI 总线协议学习笔记(3) 从本篇开始,详细翻译并学习AXI协议的官方发布规范。 文档中的时序图说明: AXI指&#xff1…

基础面试题:堆和栈的区别

面试题:堆和栈的区别(往往讲的是内存zha) 为什么说访问栈栈比访问堆快些? 目录 一、数据结构中的堆栈 1、数据结构中的堆 1)堆的定义 2)堆的效率 2、 数据结构中的栈 二、内存中的堆栈 1、内存堆的定义…

Stm32 for arduino STM32G071GBU6 I2C and SERIAL

文件目录: C:\Users\Administrator\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.3.0\variants\STM32G0xx\G071G(6-8-B)U_G081GBU boards_entry.txt Generic G071GBUx GenG0.menu.pnum.GENERIC_G071GBUXGeneric G071GBUx GenG0.menu.pnum.GENERIC…

SpringMVC:统一异常处理(11)

统一异常处理1. 说明2. 问题描述3. 异常处理器使用3.1 创建异常处理器类3.2 让程序抛出异常3.3 测试4. 项目异常处理方案4.1 异常分类4.2 异常解决方案4.3 异常解决方案的具体实现4.4 测试5. 总结1. 说明 \quad本篇文章是在文章SpringMVC:SSM整合(Spring…

【Vuex 源码学习】第六篇 - Vuex 的模块收集

一,前言 上一篇,主要介绍了 Vuex 中 Mutations 和 Actions 的实现,主要涉及以下几个点: 将 options 选项中定义的 mutation 方法绑定到 store 实例的 mutations 对象;创建并实现 commit 方法(同步&#x…

最近挺火的人工智能chatGPT注册

文章目录1.前提预备1.1 短信接收平台1.2 ip加速,不做说明2.注册chatGPT步骤2.1 进入chat.openai.com网址后,点击sign up2.2 可以使用qq邮箱注册2.3 填写好邮箱,然后点击Continue,然后再填写密码2.4 之后在qq邮箱进行验证注册(注意&#xff1a…

C++入门——内存管理

C入门——内存管理 C/C内存分布 分类是为了更好的管理 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pChar3 "abcd";int* ptr1 (…

Java、JSP环境保护与宣传网站的设计与实现

技术:Java、JSP等摘要:本文对环境保护与宣传网站的设计和开发过程进行了详细地分析与叙述。按照系统开发的实际操作流程以及论文编写的规范,论文内容从系统概述、系统分析、系统设计和系统实现这四大模块对系统的开发过程分别进行了阐述。系统…

python3-API流量回放/锲约测试/自动化测试

PPL-Tester 简介 http工具集,通过代理获取到API的请求与响应信息,将这些请求信息进行流量回放/锲约测试或快速生成用例, 亦可通过人工进行修改参数化提取、变量引用、断言等形成API自动化测试用例等! 你以为只是流量回放吗?错~走去瞧瞧v2版本! 看官~请记得给个star呗? 项…

驱动 | Linux | NVMe - 1. 概述

本文主要参考2篇相关的解析 1’ 2 和 linux 源码 3。 此处推荐一个可以便捷查看 linux 源码的网站 bootlin 4。 更新:2022 / 02 / 11 驱动 | Linux | NVMe - 1. 概述与nvme_core_init函数解析NVMe 的前世今生NVMe CommandPCI 总线从架构角度看 NVMe 驱动NVMe 驱动的…

前端开发中如何处理接口数据过大的问题

题引: 当我们在公司做项目的时候,难免会遇到后端接口直接给你返回成千上万的数据进行渲染。如果我们直接一股脑遍历添加的话,就会导致空白页面的等待时间是很长且异常卡顿,那么对于数据过大的渲染就需要进行特殊的处理。这也是一…

PyQt5数据库开发1 4.1 SQL Server 2008 R2如何开启数据库的远程连接

文章目录 前言 步骤/方法 1 使用windows身份登录 2 启用混合登录模式 3 允许远程连接服务器 4 设置sa用户属性 5 配置服务器 6 重新登录 7 配置SSCM 8 确认防火墙设置 注意事项 前言 SQL Server 2008 R2如何开启数据库的远程连接 SQL Server 2008默认是不允许远程连…

ExecutorService、Callable、Future实现有返回结果的多线程原理解析

在并发多线程场景下,存在需要获取各线程的异步执行结果,这时,就可以通过ExecutorService线程池结合Callable、Future来实现。 我们先来写一个简单的例子—— public class ExecutorTest {public static void main(String[] args) throws Ex…

KMP 算法

1 应用场景-字符串匹配问题  字符串匹配问题:: 有一个字符串 str1 ““硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好””,和一个子串 str2“尚硅谷你尚硅 你” 2) 现在要判断 str1 是否含有 str2, 如果存在,就返回第一次出现…

数据与C(limits.h数据常数介绍)

本章简单的介绍一下limits.h的数据常量,这里简单了解一下就好了 目录 一.limits.h 二.float.h头文件 一.limits.h CHAR_BIT char类型的位数 CHARMAX char类型的最大值 CHAR_MIN char类型的最小值 SCHAR_MAX signed char类型的最大…

SpringBoot图片上传和访问路径映射

图片上传和静态资源映射编写controller层接口上传到文件夹相关配置1 application.properties配置文件:2 Constant类:文件的资源映射配置WebMvcConfigurer的继承类注意测试编写controller层接口 ApiOperation("图片上传功能")PostMapping(&quo…

Java笔记-volatile和AtomicInteger

目录1. volatile1.1.什么是volatile1.2.JMM-Java内存模型2 验证volatile的特性2.1 可见性2.2.验证volatile不保证原子性2.3 volatile实现禁止指令重排序3.使用AtomicInteger解决volatile的不能实现原子性的问题3.2 AtomicInteger的方法说明:3.3 CAS3.4 应用1. volat…

linux-进程1-进程概述

写在最前 记录一下linux的进程学习专题 1. 程序和进程的区别 1.1 程序 程序是包含一系列信息的文件,这些信息描述了如何在运行时创建一个进程: 二进制格式标识:每个程序文件都包含用于描述可执行文件格式的元信息。内核利用此信息来解 释文…