一、初识IO系统
I/O系统==输入/输出系统,可以把数据输入到计算机或者接收计算机输出数据的外部设备。 例如上图中需要完成一段C语言代码的执行,需要外部键盘的介入,那就要思考一下CPU是如何知道我们键盘做完了这部分操作呢? 两种方式:①上图的程序查询方式 意思就是CPU这个大脑会不断的去问PSW(状态寄存器)这个负责人:"输入好了没有啊?",PSW回答:"好了",CPU收到回复就去指定的寄存器去取出数据,这种方式非常低效,需要CPU浪费资源反复去问。②程序中断方式 意思就是CPU在等待I/O设备办事的过程中,并没有闲着,而是去处理其他工作了,待到I/O小弟办完事(准备好数据)并通过中断信号通知CPU大哥,大哥就立刻过去把数据取走,这种方式就比较高效,靠CPU给程序中断标志来标记执行。 那又有一个问题,如果I/O设备很快,就是小弟办事很利索,每干好大哥交代的一件事就喊一次大哥,会导致什么问题?答:CPU大哥会花费更多的时间来处理中断服务程序(即保存现场、设置中断标志等),安排好再去处理I/O的,反复的上下文切换的过程影响CPU利用率,中断可能也会导致系统不稳定。
那引入第三种DMA控制方式 理解为一个更智能的I/O小弟------DMA控制器 ,这个小弟不仅能够独立完成数据搬运 工作,还能直接与内存这位大仓库管理员打交道。每次CPU大哥分配任务后,大哥很省心就去做别的事了,DMA小弟拿到任务就自己向总线仲裁器申请总线控制权 (仲裁方式详见:中央处理器)。一旦拿到权限,DMA小弟就将数据块从I/O设备传输到内存或从内存传输到I/O设备,运完所有数据后DMA控制器释放总线控制权 ,并通过中断信号通知 CPU操作已完成,CPU大哥通过接收中断 或查询状态的方式得知数据已准备好,并根据需要去内存中取走数据进行后续计算,整个过程无需CPU大哥参与,大大减少了CPU的负担。
然而,随着业务的越做越大,需要连入的I/O设备越来越多,咋办呢?引入通道控制方式 我们可以将DMA控制器比作一位能干的小组长,而通道控制方式则更像是一个部门经理级别的角色。在通道控制方式下:CPU大哥找了一个特别助理---通道经理(可以理解为是"弱鸡版的CPU) 。这位通道经理拥有独立处理I/O事务 的能力,并且可以同时管理多个DMA 小弟(即设备控制器)。当CPU需要执行一项复杂的I/O任务时,比如从多个磁盘、网络或高速设备读取大量数据并写入内存的不同区域,它会向通道经理下达指令。通道经理接到任务后,不仅能够直接与内存大仓库管理员交互,而且还能根据预先设定好的通道程序自主调度各个DMA小弟的工作,让它们各自负责不同的数据传输部分,每个DMA小弟就像之前那样可以直接进行数据搬移。在整个过程中,CPU大哥只需与通道经理打交道一次,下达高级指令后就可以放手去做其他更重要的工作。大哥更自由了。。。
二、输入/输出设备
三、输入/输出接口
I/O接口:又称I/O(设备)控制器,负责协调主机与外设之间的数据传输。
- 数据缓冲 :通过数据缓冲寄存器(DBR)达到主机和外设工作速度的匹配 解释:由于CPU和外设之间的速度差距是很大的,所以I/O接口的第一个作用就是作为数据缓冲寄存器,外设慢慢的写,当写满后CPU快速取走。
- 错误或状态监测 :通过状态寄存器反馈设备的各种错误、状态信息,供CPU查用 解释:CPU需要检测连接在电脑上的各种各样的外设状态,状态的变化需要修改状态寄存器的状态,CPU需要查状态寄存器了解各种外设的工作情况
- 控制和定时 :接收从控制总线发来的控制信号、时钟信号 解释:I/O接口收到CPU发过来的命令之后,需要给相应的IO设备发出控制信号,另外为了各种外设和主机之间相互协调,所以需要IO接口接收CPU发出的一系列时钟信号
- 数据格式转换 :串-并、并-串等格式转换 解释:很多设备输入的数据是串行的,而CPU的一般是并行的需要IO接口进行数据格式的转换
- 与主机和设备通信:实现主机---I/O接口---I/O设备之间的通信
⭐⭐⭐口语化IO接口工作流程 ⭐⭐⭐:CPU想操控打印机执行一个打印任务。首先,CPU需要把一串二进制码的打印命令输入到控制寄存器当中**(第一步:发命令),由于每个外设识别二进制位的差别,所以需要驱动程序的协助。在发出命令之后,在IO控制逻辑的指挥下根据CPU发出的命令字对设备发出一系列的控制电信号,用这样的方式来启动打印机。接下来CPU要从状态寄存器PSW中读取状态字,用这种方式来确定设备是否已经就绪或者完成打印任务 (第二步:读状态),对于打印机这个设备来说,接下来CPU需要通过数据总线往数据缓冲寄存器写入想要打印的数据,然后再在控制逻辑的操控之下把这些数据逐个的输出到打印机当中 (第三步:读写数据)**,打印机完成之后就可以给IO接口一个状态的反馈,当IO接口收到反馈就去修改状态寄存器相应的比特位,这样CPU就可以通过PSW读到IO操作的完成(CPU可以通过程序查询和中断请求方式获取IO操作状态) 那为什么图中吧状态寄存器和控制寄存器合二为一呢? 解释:因为CPU是先发出控制信号,一旦取出这个命令字后,该寄存器就会空闲,可以让该寄存器接下来存储状态字,因为使用时间上面是刚好重复错开的,所以很多IO接口把两个寄存器合二为一是为了合理利用。 地址线的作用 :CPU会通过地址线来确定需要往哪个IO端口(CPU和寄存器之间)寄存器读/写数据 控制总线的作用 :指明对这个IO端口是执行读还是写命令,还可以用于给CPU反馈中断请求信号 数据总线的作用:CPU输出,外设输入的数据通过数据总线的传输放入数据缓存寄存器当中,还可以传输中断类型号(CPU结合数据总线+PSW的类型明确是哪种中断类型)
引申:CPU通过IO接口可以操作很多设备,那CPU是如何做操作和选择的呢? 第一种:通过地址线指明具体的设备编号,但需要分开两次进行传输 第二种:几组设备就再加几组数据、状态寄存器,比喻操作多组不同的设备
由于接口内部会有多个接口、多个寄存器,那对寄存器和端口采取什么样的编制呢?
统一编制(存储器映射方式) :IO端口地址和内存地址是一套的,例如图中的0---N-1是内存地址,N---N+5是IO端口地址,理解为同一套标准进行唯一性编制 优点:所有访存指令可以直接访问端口,设计灵活性高读写控制电路更简单,端口编制空间更大 缺点:主存空间变小,地址位数多,地址译码速度慢 独立编制(I/O映射方式) :IO端口地址和内存地址是相互独立的,例如0-5地址是有重复的,需要专门的I/O指令(IN、OUT)访问I/O端口,理解为专人做专事,携带不同标准区分内存和I/O 优点:不占用主存空间,地址位数少,地址译码速度快,程序编制清晰 缺点:灵活性差读写控制电路明显复杂
下面看一下I/O接口常见的一些分类:
-
按数据传送方式划分
-
并行接口:一个字节或一个字所有位同时传送
-
串行接口:一位一位地传送
注!:这里所说的数据传送方式指的是外设和接口一侧的传送方式,而在主机和接口一侧,数据总是并行传送的。接口要完成数据格式转换
-
-
按主机访问I/O设备的控制方式划分(后面做详解)
- 程序查询
- 中断接口
- DMA接口
-
按功能选择灵活性划分
- 可编程接口
- 不可编程接口
四、程序查询方式
如流程图所示:首先,CPU会初始化一些参数,并设置好要与之通信的数据首地址。然后向I/O接口发送命令字来启动外设设备。接着,CPU开始不断地检查I/O设备的状态信息,直到设备准备好可以接收数据为止。在这个过程中,CPU必须停止当前正在运行的程序并插入一段等待代码以确保不会影响到其他操作。一旦设备准备就绪,CPU就会将数据传送到设备上。在每次传送之后,它都会修改一下计数器和地址等参数以便进行下一轮的读写操作。当所有的数据都已经被成功地送到了设备后,CPU就可以判断这次传送是否已经结束(通常情况下是在计数值为0时)。如果所有数据都已经送达,则表示本次传送已完成;否则就需要再次重复上述步骤直至完成全部数据的传递工作。
主要特点 :CPU有"踏步"等待现象,CPU与I/O串行工作。 优点 :接口设计简单、设备量少。 缺点 :CPU用于查询和等待耗时,独占查询 (CPU 100%的时间都在查询I/O状态,完全串行)较低效率,定时查询(保证数据不丢失的前提下每隔一段时间查询一次I/O状态,时间间隔内可以执行其他程序)
例题:在程序查询方式的输入/输出系统中,假设不考虑处理时间,每一个查询操作需要100个时钟周期,CPU的时钟频率为50MHz。现有鼠标和硬盘两个设备,而且CPU必须每秒对鼠标进行30次查询,硬盘以32位字长为单位传输数据,即每32位被CPU查询一次,传输率为2×220B/s。求CPU对这两个设备查询所花费的时间比率,由此可得出什么结论?
时间的角度: 一个时钟周期为1/50MHz = 20ns 一个查询操作耗时100 × 20ns = 2000ns 1)鼠标 每秒查询鼠标耗时30 × 2000ns = 60000ns 查询鼠标所花费的时间比率= 60000ns/1s = 0.006% 对鼠标的查询基本不影响CPU的性能 2)硬盘 每32位需要查询一次,每秒传送2×2^20B 每秒需要查询(2×2^20B)/4B = 2^19次 查询硬盘耗时2^19× 2000ns = 512 × 1024 × 2000ns ≈ 1.05×10^9 ns 查询硬盘所花费的时间比率= (1.05×10^9 ns)/1s = 105% 结论:CPU将全部时间都用于对硬盘的查询也不能满足磁盘传输的要求
频率的角度: CPU的时钟频率为50MHz,即每秒50×10^6个时钟周期 1)鼠标 每秒查询鼠标占用的时钟周期数30 × 100 = 3000 查询鼠标所花费的时间比率= 3000/(50×10^6) = 0.006% 对鼠标的查询基本不影响CPU的性能 2)硬盘 每秒需要查询(2×2^20B)/4B = 2^19次 每秒查询硬盘占用的时钟周期数2^19× 100≈ 5.24×10^7 查询硬盘所花费的时间比率= (5.24×10^7 )/(50×10^6) ≈ 105% 结论:CPU将全部时间都用于对硬盘的查询也不能满足磁盘传输的要求
五、程序中断方式
首先引入中断的概念:计算机在执行程序的过程中遇到了一些异常情况,CPU会记录中断点执行中断程序,挂起当前程序转去处理别的异常情况,在处理完毕后自动折返到当前断点,继续执行原程序。
工作流程:
- 中断请求 中断源向CPU发送中断请求信号。
- 中断响应 响应中断的条件。(CPU自助判断是否想要响应,如【关中断】,CPU就不会去理会,本质是在PSW中会通过IF的值来判断【1代表开中断,2代表关中断】) 需要响应就需要中断判优:多个中断源同时提出请求时通过中断判优逻辑响应一个中断源,判断响应优先级。
- 中断处理 中断进行处理需要中断隐指令 :通过中断隐指令的帮助,把CPU的指令执行流转移 到正确的中断程序这,本质上是修改PC的值。
如何判断是哪个设备发来的中断信号? 解答:那就需要引入中断请求标记寄存器 ,它可以集成于CPU内部 或者分散在各个中断源 中。 中断系统需对每个中断源设置中断请求标记触发器INTR ,当其状态为**"1"时,表示中断源有请求,这些触发器可组成中断请求标记寄存器**。
对于外中断,CPU是在统一的时刻即每条指令执行阶段结束前向接口发出中断查询信号,以获取I/O的中断请求,也就是说,CPU响应中断的时间是在每条指令执行阶段的结束时刻。 CPU响应中断 必须满足以下3个条件: ① 中断源有中断请求 ② CPU允许中断即开中断 ③ 一条指令执行完毕,且没有更紧迫的任务
多个中断信号,那又是如何进行判优处理的呢? 显然,这可以通过硬件和软件实现,硬件是通过硬件排队器 实现【对各个外设的中断源进行电路的排序】
你先:硬件故障中断、非屏蔽中断、DMA请求、高速设备、输入设备、实时设备 你后:软件中断、可屏蔽中断、I/O设备请求、低速设备、输出设备、普通设备
那CPU是怎么做到在处理完异常情况后精准无误的返回到异常前的地方的呢?那就需要引入中断隐指令 中断隐指令要做两件事:①保存原程序的PC值 ②让PC指向中断服务程序的第一条指令
其中要强调中断隐指令并不是一条具体的CPU指令,其背后需要执行很多的指令相当于一个一系列的任务【CPU自动完成】
中断隐指令的主要任务:
- 首先进行关中断,防止被新的中断请求打断
- 然后要保存断点,为了保证中断服务程序完毕后能正确的回到原来的程序,用的是堆栈信息存储
- 最后就是要引出中断服务程序,为了取出中断地址送给程序计数器PC
中断服务程序的主要任务:
- 保护现场:可使用堆栈或特定存储单元保存通用寄存器和状态寄存器的内容
- 中断服务:主体
- 恢复现场:出栈指令或取数指令送回寄存器
- 中断返回:通过中断返回指令回到程序断点处
那PC的值要如何保存,保存在什么地方呢?PC的值保存之后应该如何找到特定的中断服务程序呢? 找到中断程序的入口地址,理解上图的硬件向量法,首先上文介绍过硬件排队器会输出对应的中断源信号,这个输出信号会作为中断向量地址形成部件的输入,处理后会输出向量地址(中断类型号),向量地址作为指针的指针指向主存中的某一处JMP中断向量,再通过中断向量指针指向中断程序的入口地址。
在整个执行过程中,一直会循环顺序的取指令、执行指令 ,在每一个指令周期的末尾 CPU都会例行检查 ,此时是否有中断信号 需要处理,如果没有的话那就继续取出下一条指令 。假设当前取出的是K 这条指令之后,检测到了一条中断请求信号 ,此时PC的值是指向了下一条指令 的位置,接下来CPU检测到中断信号 之后,会自动的完成一系列的动作,也就是中断隐指令 要完成的一系列任务 ,首先要做的是把之前的这个程序执行 的断点信息PC值 压入栈中保存下来,接着执行一条关中断指令 【硬件完成这两个动作,可以同时执行】除此之外还需要硬件电路得到这个中断请求信号 对应的向量地址 ,然后再通过向量地址 得到中断向量 ,最后把中断向量 赋给PC ,这样程序就会指向中断服务程序的入口地址 ,开始接下来的执行中断服务 程序。而接下来要做的第一件事就是要保护现场 【保存各种寄存器的值】,之后进行具体的处理,处理完之后就恢复现场 ,最后再执行一条开中断 的指令再让PC的值重新指回以前的程序,回到以前的位置。此时就是完整的流程。【补充:关中断和开中断之间一整堆的执行流程一定是一气呵成的,不会被打断,此时有中断请求也会等我执行完再去响应。而这仅仅是单重中断的处理方式,实际情况下则不会满足,就需要引出下文的多重中断请求】
多重中断
背景 :多重中断又称为中断嵌套,可能会存在执行中断程序的过程中又遇到新的中断请求 那为什么再一次的开中断、关中断要在图中那个位置呢? 解释:因为需要保证保存现场和恢复现场是一气呵成的,不能出现保存一半,恢复一半的情况
相比较于单重中断,多重中断就多了一端开关中断的过程和屏蔽字,那屏蔽字是干嘛的呢? 解释:屏蔽字也叫做中断屏蔽字,由于系统中有多个中断请求信号,本质上也要区分这些请求的优先级,需要中断屏蔽字来屏蔽部分低优先级的中断请求。
中断屏蔽技术 【最右边的电路越多,表示其优先级越高,那么被屏蔽的可能性就越大 ,其中'1'表示屏蔽,'0'表示正常申请】
执行流程:
- 当CPU接收到一个中断请求时,会根据预先设置好的中断屏蔽策略,检查当前的中断屏蔽字来决定是否允许执行这个中断。
- 在进入中断服务程序(ISR, Interrupt Service Routine)前,通常会先打开(允许)更高优先级中断的发生,这样就实现了多重中断------即使在处理低优先级中断的过程中,系统也能响应高优先级的新中断。
- 在执行ISR的关键部分(如现场保护、敏感数据操作等)时,为了保证这些操作的原子性,会临时关闭(屏蔽)所有中断或特定中断源,以防止被打断。
- 在ISR结束阶段,恢复现场后,再根据需要重新设定中断屏蔽字,恢复之前的中断使能状态或按照新的调度策略调整中断系统的状态。
例题:设某机有4个中断源A、B、C、D,其硬件排队优先次序为A>B>C>D,现要求将中断处理次序改为D>A>C>B。 1)写出每个中断源对应的屏蔽字。 2)按下图所示的时间轴给出的4个中断源的请求时刻,画出CPU执行程序的轨迹。设每个中断源的中断服务程序时间均为20us。 解答:首选需要明确'1'表示屏蔽,'0'表示正常申请,按照中断优先级处理次序可以确定B的优先级最小,但是要屏蔽自身所以可以确定为0100,C的是0110,A的是1110,D的是1111 图示则是按照优先级的插入来算,没断执行时间是20us
六、DMA方式
DMA方式的特点 :引入DMA,I/O设备和主机之间可以并行工作,CPU的运行程序和传送数据也可以并行执行 大前提:下图的流程图是基于单总线结构 ,图中对应DMA方式的部件及其功能
⭐⭐⭐口述上图的DMA执行流程 ⭐⭐⭐:首先,预处理的阶段,CPU会向DMA 小弟指明接下来要读/写的数据应该存放在主存的什么位置,预处理阶段 需要准备数据 ,指明主存地址的主存寄存器 (AR)读写指针,指明I/O设备地址的寄存器DAR ,指明需要传送多少个数据的寄存器WC ,在准备阶段完成后就启动IO设备了。接下来就由DMA控制器 控制住数据传送 的过程【CPU可以继续执行之前的程序,不用管这个数据传送的过程】,假设此时需要传送一个数据,数据首先要填充到数据缓冲寄存器DR 中,同时向DMA触发器 发出一个高电平信号1,当控制逻辑检测到DMA请求 ,也就是1个字的数据传送已经完成之后,它就会向CPU申请总线的控制权 【HRQ】,如果系统总线可以把控制权给DMA控制器,那CPU就会给它一个反馈的信号 【HLDA】,现在DMA获得了总线的控制权,接下来就可以通过控制线,地址线、数据线 给主存发出读/写命令 ,同时会把数据缓冲寄存器 的几个bit信息打到数据线上,把主存的地址信息打到地址线上,这样就完成了一个字的数据传输 。数据传输完之后,需要让主存的地址自动的后移,同时修改长度计数器 。那传输完多个字之后,长度计数器会发生溢出,溢出信号 会传送给中断机构,中断机构检测到溢出信号之后会给CPU发出中断请求,接下来CPU会对DMA的中断信号进行处理【DMA请求 和DMA中断请求 ,一个是传送一个字的数据,另一个意味着一整块的数据已经完成需要CPU介入】,CPU收到中断请求之后就会进行后处理 ,也就是运行相应的中断服务程序做DMA结束的善后工作 。所以总的来说,DMA方式的传送过程需要经历预处理、数据传送、后处理 三个过程。 重点:程序中断方式每一个字的传送都需要CPU进行搬运,DMA方式意味着由小弟搬完一整块的数据之后CPU才进行一次响应
如果出现下图中的三总线结构,CPU和DMA会出现同时访问主存的情况,因此就会出现DMA传送方式的冲突问题
那如何解决这个问题呢?提出三种解决方案
-
停止CPU访问主存
整个过程主权都交给DMA控制器,CPU没法取走指令,所以这种方式的优点就是控制简单【简单粗暴】,同样伴随的缺点就是CPU不工作,利用率不高,违背引入DMA的初衷。
-
DMA与CPU交替访存 让CPU和DMA有规律的交替访问主存,时间片的划分是死的,这种方式的优点是不需要总线使用权的申请,但是实现也会相对复杂。另外,如果CPU的访问是十分频繁的,划分时间片的这种方式也不会充分的利用CPU。
-
周期挪用(周期窃取) DMA访存的三种情况: ① CPU 此时不访存(不冲突),DMA进入访存 ② CPU 正在访存(存取周期结束让出总线),DMA等待CPU访存结束再进入 ③ CPU 与DMA 同时请求访存(I/O访存优先),【优先DMA】原因是DMA中的数据缓冲寄存器如果不及时的写入主存会导致数据的丢失