计算机最魔幻的事情就是它能感知到你的思想(三)

简介: 我们之前的文章提到了操作系统的三个抽象,它们分别是进程、地址空间和文件,除此之外,操作系统还要控制所有的 I/O 设备。操作系统必须向设备发送命令,捕捉中断并处理错误。它还应该在设备和操作系统的其余部分之间提供一个简单易用的接口。操作系统如何管理 I/O 是我们接下来的重点。

DMA 工作原理


当使用 DMA 后,这个过程就会变得不一样了。首先 CPU 通过设置 DMA 控制器的寄存器对它进行编程,所以 DMA 控制器知道将什么数据传送到什么地方。DMA 控制器还要向磁盘控制器发出一个命令,通知它从磁盘读数据到其内部的缓冲区并检验校验和。当有效数据位于磁盘控制器的缓冲区中时,DMA 就可以开始了。

DMA 控制器通过在总线上发出一个读请求到磁盘控制器而发起 DMA 传送,这是第二步。这个读请求就像其他读请求一样,磁盘控制器并不知道或者并不关心它是来自 CPU 还是来自 DMA 控制器。通常情况下,要写的内存地址在总线的地址线上,所以当磁盘控制器去匹配下一个字时,它知道将该字写到什么地方。写到内存就是另外一个总线循环了,这是第三步。当写操作完成时,磁盘控制器在总线上发出一个应答信号到 DMA 控制器,这是第四步。

然后,DMA 控制器会增加内存地址并减少字节数量。如果字节数量仍然大于 0 ,就会循环步骤 2 - 步骤 4 ,直到字节计数变为 0 。此时,DMA 控制器会打断 CPU 并告诉它传输已经完成了。操作系统开始运行时,它不会把磁盘块拷贝到内存中,因为它已经在内存中了。

不同 DMA 控制器的复杂程度差别很大。最简单的 DMA 控制器每次处理一次传输,就像上面描述的那样。更为复杂的情况是一次同时处理很多次传输,这样的控制器内部具有多组寄存器,每个通道一组寄存器。在传输每一个字之后,DMA 控制器就决定下一次要为哪个设备提供服务。DMA 控制器可能被设置为使用 轮询算法,或者它也有可能具有一个优先级规划设计,以便让某些设备受到比其他设备更多的照顾。假如存在一个明确的方法分辨应答信号,那么在同一时间就可以挂起对不同设备控制器的多个请求。

许多总线能够以两种模式操作:每次一字模式和块模式。一些 DMA 控制器也能够使用这两种方式进行操作。在前一个模式中,DMA 控制器请求传送一个字并得到这个字。如果 CPU 想要使用总线,它必须进行等待。设备可能会偷偷进入并且从 CPU 偷走一个总线周期,从而轻微的延迟 CPU。这种机制称为 周期窃取(cycle stealing)

在块模式中,DMA 控制器告诉设备获取总线,然后进行一系列的传输操作,然后释放总线。这一操作的形式称为 突发模式(burst mode)。这种模式要比周期窃取更有效因为获取总线占用了时间,并且一次总线获得的代价是可以同时传输多个字。缺点是如果此时进行的是长时间的突发传送,有可能将 CPU 和其他设备阻塞很长的时间。

在我们讨论的这种模型中,有时被称为 飞越模式(fly-by mode),DMA 控制器会告诉设备控制器把数据直接传递到内存。一些 DMA 控制器使用的另一种模式是让设备控制器将字发送给 DMA 控制器,然后 DMA 控制器发出第二条总线请求,将字写到任何可以写入的地方。采用这种方案,每个传输的字都需要一个额外的总线周期,但是更加灵活,因为它还可以执行设备到设备的复制,甚至是内存到内存的复制(通过事先对内存进行读取,然后对内存进行写入)。

大部分的 DMA 控制器使用物理地址进行传输。使用物理地址需要操作系统将目标内存缓冲区的虚拟地址转换为物理地址,并将该物理地址写入 DMA 控制器的地址寄存器中。另一种方案是一些 DMA 控制器将虚拟地址写入 DMA 控制器中。然后,DMA 控制器必须使用 MMU 才能完成虚拟到物理的转换。仅当 MMU 是内存的一部分而不是 CPU 的一部分时,才可以将虚拟地址放在总线上。


重温中断


在一台个人计算机体系结构中,中断结构会如下所示

30.png

当一个 I/O 设备完成它的工作后,它就会产生一个中断(默认操作系统已经开启中断),它通过在总线上声明已分配的信号来实现此目的。主板上的中断控制器芯片会检测到这个信号,然后执行中断操作。

如果在中断前没有其他中断操作阻塞的话,中断控制器将立刻对中断进行处理,如果在中断前还有其他中断操作正在执行,或者有其他设备发出级别更高的中断信号的话,那么这个设备将暂时不会处理。在这种情况下,该设备会继续在总线上置起中断信号,直到得到 CPU 服务。

为了处理中断,中断控制器在地址线上放置一个数字,指定要关注的设备是哪个,并声明一个信号以中断 CPU。中断信号导致 CPU 停止当前正在做的工作并且开始做其他事情。地址线上会有一个指向中断向量表 的索引,用来获取下一个程序计数器。这个新获取的程序计数器也就表示着程序将要开始,它会指向程序的开始处。一般情况下,陷阱和中断从这一点上看使用相同的机制,并且常常共享相同的中断向量。中断向量的位置可以硬连线到机器中,也可以位于内存中的任何位置,由 CPU 寄存器指向其起点。

中断服务程序开始运行后,中断服务程序通过将某个值写入中断控制器的 I/O 端口来确认中断。告诉它中断控制器可以自由地发出另一个中断。通过让 CPU 延迟响应来达到多个中断同时到达 CPU 涉及到竞争的情况发生。一些老的计算机没有集中的中断控制器,通常每个设备请求自己的中断。

硬件通常在服务程序开始前保存当前信息。对于不同的 CPU 来说,哪些信息需要保存以及保存在哪里差别很大。不管其他的信息是否保存,程序计数器必须要被保存,这对所有的 CPU 来说都是相同的,以此来恢复中断的进程。所有可见寄存器和大量内部寄存器也应该被保存。

上面说到硬件应该保存当前信息,那么保存在哪里是个问题,一种选择是将其放入到内部寄存器中,在需要时操作系统可以读出这些内部寄存器。这种方法会造成的问题是:一段时间内设备无法响应,直到所有的内部寄存器中存储的信息被读出后,才能恢复运行,以免第二个内部寄存器重写内部寄存器的状态。

第二种方式是在堆栈中保存信息,这也是大部分 CPU 所使用的方式。但是,这种方法也存在问题,因为使用的堆栈不确定,如果使用的是当前堆栈,则它很可能是用户进程的堆栈。堆栈指针甚至不合法,这样当硬件试图在它所指的地址处写入时,将会导致致命错误。如果使用的是内核堆栈,堆栈指针是合法的并且指向一个固定的页面,这样的机会可能会更大。然而,切换到内核态需要切换 MMU 上下文,并且可能使高速缓存或者 TLB 失效。静态或动态重新装载这些东西将增加中断处理的时间,浪费 CPU 时间。


精确中断和不精确中断


另一个问题是:现代 CPU 大量的采用流水线并且有时还采用超标量(内部并行)。在一些老的系统中,每条指令执行完毕后,微程序或硬件将检查是否存在未完成的中断。如果存在,那么程序计数器和 PSW 将被压入堆栈中开始中断序列。在中断程序运行之后,旧的 PSW 和程序计数器将从堆栈中弹出恢复先前的进程。

下面是一个流水线模型

31.png

在流水线满的时候出现一个中断会发生什么情况?许多指令正处于不同的执行阶段,中断出现时,程序计数器的值可能无法正确地反应已经执行过的指令和尚未执行的指令的边界。事实上,许多指令可能部分执行,不同的指令完成的程度或多或少。在这种情况下,程序计数器更有可能反应的是将要被取出并压入流水线的下一条指令的地址,而不是刚刚被执行单元处理过的指令的地址。

在超标量的设计中,可能更加糟糕

32.png

每个指令都可以分解成为微操作,微操作有可能乱序执行,这取决于内部资源(如功能单元和寄存器)的可用性。当中断发生时,某些很久以前启动的指令可能还没开始执行,而最近执行的指令可能将要马上完成。在中断信号出现时,可能存在许多指令处于不同的完成状态,它们与程序计数器之间没有什么关系。

使机器处于良好状态的中断称为精确中断(precise interrupt)。这样的中断具有四个属性:

  • PC (程序计数器)保存在一个已知的地方
  • PC 所指向的指令之前所有的指令已经完全执行
  • PC 所指向的指令之后所有的指令都没有执行
  • PC 所指向的指令的执行状态是已知的

不满足以上要求的中断称为 不精确中断(imprecise interrupt),不精确中断让人很头疼。上图描述了不精确中断的现象。指令的执行时序和完成度具有不确定性,而且恢复起来也非常麻烦。

相关文章
|
监控 安全 Shell
【Shell 命令集合 系统管理 】Linux 获取用户信息 finger命令 使用指南
【Shell 命令集合 系统管理 】Linux 获取用户信息 finger命令 使用指南
213 0
cesium添加实体不被地形遮挡的参数设置
disableDepthTestDistance:指定从相机到禁用深度测试的距离,关于深度测试我们将在后面的文章中介绍到,由于深度测试的存在,我们的对象很多时候会被地形挡住,如下:
2843 0
cesium添加实体不被地形遮挡的参数设置
|
11月前
|
存储 安全 物联网
浅析Kismet:无线网络监测与分析工具
Kismet是一款开源的无线网络监测和入侵检测系统(IDS),支持Wi-Fi、Bluetooth、ZigBee等协议,具备被动监听、实时数据分析、地理定位等功能。广泛应用于安全审计、网络优化和频谱管理。本文介绍其安装配置、基本操作及高级应用技巧,帮助用户掌握这一强大的无线网络安全工具。
871 9
浅析Kismet:无线网络监测与分析工具
|
消息中间件 Java API
解密微服务架构:如何在Java中实现高效的服务通信
微服务架构作为一种现代软件开发模式,通过将应用拆分成多个独立的服务,提升了系统的灵活性和扩展性。然而,实现微服务之间的高效通信仍然是许多开发者面临的挑战。本文将探讨在Java环境中实现微服务架构时,如何使用不同的通信机制来优化服务之间的交互,包括同步和异步通信的方法,以及相关的最佳实践。
|
存储 安全 算法
密码学原理及其在网络安全中的应用
【7月更文挑战第27天】密码学作为保护信息安全的基石,在网络安全中发挥着不可或缺的作用。通过加密、解密、身份验证、数字签名和哈希函数等技术手段,密码学确保了数据的机密性、完整性和认证性。随着计算能力的不断提升和密码分析技术的不断进步,密码学需要不断创新和发展,以应对新的安全挑战。未来,随着量子计算技术的兴起和后量子密码学的研究深入,密码学将在网络安全领域发挥更加重要的作用。
|
存储 供应链 前端开发
2024你不得不知道的免费API
本文首发于微信公众号“前端徐徐”,介绍了 2024 年各领域的免费 API 列表,涵盖游戏、语言、音乐、安全、科学、体育、Web 应用、产品、健康、政府和地理、食品、开源项目、电影和漫画等多个类别。每个 API 均提供官网链接、简介及示例代码,帮助开发者轻松集成第三方服务,增强应用程序的功能和用户体验。
1056 4
2024你不得不知道的免费API
|
边缘计算 安全 网络安全
隐藏服务器源IP怎么操作?
一篇文章看懂隐藏源IP!
537 0
|
机器人 Java 测试技术
《手把手教你》系列技巧篇(六十)-java+ selenium自动化测试 - 截图三剑客 -中篇(详细教程)
【6月更文挑战第1天】本文介绍了使用Java和Selenium进行自动化测试时的另一种截图方法,即利用Robot类实现全屏截图。Robot类能够捕获屏幕上的所有内容,包括任务栏和浏览器元素。测试场景包括访问指定网站、调用截图方法和保存截图。示例代码展示了如何使用Robot创建全屏截图并保存到特定文件夹。在运行代码前,需确保指定的保存路径存在,否则会报错。
199 4
|
前端开发 NoSQL Redis
网页设计,若依修改05(It must be done)-----强退用户
网页设计,若依修改05(It must be done)-----强退用户
|
前端开发 NoSQL 数据库
设计 QQ、微信等第三方账号登陆
设计 QQ、微信等第三方账号登陆
184 0
设计 QQ、微信等第三方账号登陆