资源描述
Input/Output Accessing
In this article, we will look at the three basic methods of I/O accessing - programmed I/O, interrupt-driven I/O, and direct memory access (DMA). The key issue that distinguishes these three methods is how deeply the processor is involved in I/O operations. The discussion emphasizes interrupt-driven I/O, because it is based on the concept of interrupt handling, which is a general problem that goes beyond Input/Output operations. The study of interrupt handling also aids in understanding the general concept of exception processing, which is an important issue not only for I/O, but also for interfacing a computer with other system control functions.
Addressing I/O Registers
Input/Output devices communicate with a processor through Input/Output ports. Through the input ports, s processor receives data from the I/O devices. Through the output ports, a processor sends data to the I/O devices. Each I/O port consists of a small set of registers, such as data buffer registers (the input buffer and/or the output buffer), the status register, and the control register. The processor must have some means to address these registers while communicating with them. There are two common methods of addressing I/O register - memory-mapped I/O and direct I/O.
1. Memory-Mapped I/O
Memory-mapped I/O maps the I/O registers and main memory into a unified address space in the computer system. I/O registers share the same address space with main memory, but are mapped to a specific section that is reserved just for I/O. Thus, the I/O register can be addressed in ordinary memory reference instructions as if they are part of the main memory locations. There are no specially designed I/O instructions in the instruction set of the system. Any instruction that references a location in this area
外文资料原文
is an I/O instruction. Any instruction that can specify a memory address is capable of performing I/O operations. The Motorola MC68000 is an example of a computer system that uses this addressing method.
2. Direct I/O
The method of addressing I/O registers directly without sharing the address space with the main memory is called direct I/O or I/O-mapped I/O. In other words, I/O registers are not mapped to the same address space with the main memory. Each I/O register has an independent address space. As a result, instructions that reference the main memory space cannot be used for Input/Output. In the instruction set of the computer system, special I/O instructions must be designed for I/O operations. In these I/O instructions, distinct I.D. numbers must be used to address different I/O communication channels (i.e., I/O ports). They are called port numbers. The I/O registers of an I/O port are connected to the system I/O bus, through which the processor can reference the I/O registers directly to send/receive data to/from an I/O device. An I/O port number is not from the same address space as main memory. The Pentium is an example of a computer system that uses the direct I/O addressing method. It has a 64 GB memory address space (32 address bits) and, at the same time, a 64 KB I/O address space (16 bits I/O address/port number).
Programmed I/O
Programmed I/O requires that all data transfer operations be put under the complete control of the processor when executing programs. It is sometimes called polling, because the program repeatedly polls (checks) the status flag of an I/O device, so that its input/output operation can be synchronized with the processor. A general flowchart of such a program is shown in Figure 1. The program continuously polls the status of an I/O device to find out whether (1) data is available in the input buffer or (2) the output device is ready for receiving data from the processor. If the status shows “available” the program will execute a data transfer instruction to complete the I/O operation; otherwise, the busy status of the I/O device will force the program to circulate in a busy-waiting loop until the status becomes available. Such a busy-waiting loop, which continuously checks the status of data availability (for input) or device availability (for out-put), forms the typical program structure of programmed I/O. It is this time-consuming busy-waiting loop that wastes processor time and makes programmed I/O very inefficient. The processor must be involved continuously in the entire I/O process. During this time interval, the processor cannot perform any useful computation, but only serve a single I/O device. For certain slow I/O devices, this busy-waiting loop interval may be long enough that the processor could execute millions of instructions before the I/O event occurs, e.g., a key stroke on a keyboard.
The operational mode lf programmed I/O stated above is characterized by the busy waiting loop of the program, during which the processor spends time polling an I/O device. Because of the dedication of the processor to a single task, this mode of programmed I/O is called dedicated polling or spin polling. Although dedicated polling is highly inefficient, sometimes it is necessary and even unavoidable. In a particular case, if an urgent event needs an immediate response without delay, then dedicated polling by a dedicated processor may be the best way to handle it. Once the expected event happens, the processor can tract to it immediately. For example, certain real time systems (e.g., radar echo processing systems) require a reaction to incoming data that is so quick that even an interrupt response is too slow. Under such a circumstance, only a fast dedicated polling loop may suffice.
Another mode of operation of programmed I/O is called intermittent polling or timed polling. In this mode, the processor may poll the device at a regular timed interval, which can be expected or prescheduled. Such a device can be found in many embedded systems where a special-purpose computer is used for process control, data acquisition, environmental monitoring, traffic counting, etc. these devices, which measure, collect, or record data, are usually polled periodically in a regular schedule determined by the needs of the application. Such a method of intermittent polling can help save time lost in spin polling and avoid the complexity of interrupt processing. However, it should be noted that intermittent polling may not be applicable in some special cases, in which there is only one device to be polled and the correct polling rate must be achieved with the assistance of an interrupt-driven clock. Using timed polling in this case would result in simply swapping one interrupt-driven clock. Using time polling in this case would result in simply swapping one interrupt requirement for another.
Interrupt-Driven I/O
Interrupt-driven I/O is a means to avoid the inefficient busy-waiting loops, which characterize programmed I/O. Instead of waiting while the I/O device is busy doing its job of input/output, the processor can run other programs. When the I/O device completes its job and its status becomes “available”, it will issue an interrupt request to the processor, asking for CPU service. In response, the processor suspends whatever it is currently doing, in order to attend to the needs of that I/O device.
In respond to an interrupt request, the processor will first save the contents of both the program counter and the status register for the running program, and then transfer the control to the corresponding interrupt service routine to perform the required data input/output operation. When the interrupt service routine has completed its execution and if no more interrupt requests are pending, the processor will resume the execution of the previously interrupted program and restore the contents of the statuses and program counter. The processor hardware should check the interrupt request signal upon completion of execution of every instruction. If multiple devices issue their interrupt requests at the same time, the processor must use some method to choose which one to service first, and then service all the other interrupt requests one by one by order of priority. Only after all the interrupt requests have been serviced will the CPU return to the interrupted user program. In this way, the processor can serve many I/O devices concurrently and spend more time doing useful jobs, rather than running a busy-waiting loop to serve a single device. Therefore, interrupt I/O is very effective in handling slow and medium-speed I/O devices. Furthermore, the concept of an interrupt can be generalized to handle any event caused by hardware or software, internally or externally. This general problem is referred to as exception processing.
If multiple interrupt requests are issued by different devices at the same time, the processor should have some means to identify the interrupt sources and handle their interrupt requests by some policy, typically by priority. Only one request with the highest priority can be serviced at the current time, while all others are put into a waiting queue. Upon the completion of the service performed by an interrupt service routine, the processor should search the waiting queue for all the pending interrupt requests, old or new, and continue to service them one by one according to their priorities, until the queue becomes empty. Only when all the pending interrupt requests have been serviced can the interrupted user program be resumed. Although this case contains multiple interrupt requests, it is still a simplified case. The assumption is that all the interrupt service routines must be completed without further interruption 9 (or so-called preemption) once they have been started one after another by the processor. An interrupt process satisfying this assumption is called a non-preemptive interrupt. In real-life circumstances, the process of interrupt-driven I/O can be more complicated than this simplified case. Each interrupted service routine running in the processor can be preempted (interrupted) by a newly arrived interrupt request, which has a higher priority than the current one. This circumstance will cause the main program and all the requested interrupt service routines to have a complicated interrelationship. An interrupt process that allows an interrupt service routine to be preempted by a higher-priority interrupt service routine is called a preemptive interrupt.
翻译文稿
输入/输出访问
在这一篇文章中,我们将会研究三种基本的输入/输出访问方法:程控I/O、中断驱动I/O以及直接存储器访问(DMA)。 区别这三个方法的关键问题是处理器以怎样的深度介入I/O操作。讨论的重点是中断驱动I/O,这是因为它的基础是中断处理概念,而这是一个超过输入输出操作之外的普遍性问题。学习中断
处理也有助于了解异常事件处理这一普遍性概念,其重要性不但有关I/O,而且有关计算机与其他系统控制函数的接口。
I/O寄存器的寻址
输入/ 输出设备经过输入/ 输出端口与一个处理机通信。经过输入端口,处理器接受来自输入/输出装置的数据。经过输出端口,处理器送数据给输入/输出装置。每个输入/输出端口包含一个小的寄存器组, 如数据缓冲寄存器 (输入缓冲器和/或输出缓冲器)、状态寄存器和控制寄存器。处理器必须有某种方法寻
址这些寄存器,同时与它们通信。寻址输入/输出寄存器有存储器映射输入/输出和直接输入/输出两种方法。
1.存储器映射的输入/输出
存储器映射的输入/输出将输入/输出寄存器和存储器一起映射到计算机系统的统一的住址空间。输入/输出寄存器共享主存储器的同一个地址空间, 但是被映射到一个特定的专为输入/输出预留的存储器区段。因此,输入/输出寄存器能在普通的存储器访问指令中得到寻址,好像它们就是主存储器位置的一部份。在计算机的指令系统中没有专门设计的 输入/输出指令。任何访问这一地区中某个位置的指令便是一条输入/输出指令。任何的一条可以指定存储器地址的指令都可以执行输入/输出操作。摩托罗拉 MC68000 就是使用这种寻址方法的计算机系统的一个例子。
2. 直接输入/输出
直接地向输入/输出寄存器寻址而不和主存储器共享地址空间的寻址方法叫做直接输入/输出或输入/输出映射输入/输出。换句话说,输入/输出寄存器不和主存储器映射到同一个地址空间。每个输入/输出寄存器有一个独立的地址空间。其结果是:访问主存储器空间的指令不能够作用于输入/输出。在计算机系统的指令系统中,必须为输入/输出操作 设计专门的指令。在这些输入/输出指令中,必须用各自不同的标号来寻址不同的输入/输出交换通道。它们被称作端口号。输入/输出端口的输入/输出寄存器连接到系统输入/输出总线上,处理器经过它可以直接访问输入/输出寄存器向 / 从输入/输出装置发送 / 接收数据。使用端口号的方式和使用存储器地址的方式相同,但不同的是端口号不是来自主存储器的同一地址。 Pentium 是使用直接输入/输出寻址法的计算机系统的例子。它有 64 GB 存储地址空间 (32 位住址),同时,还有一个 64 KB 输入/输出地址空间 (16 位输入/输出住址/ 端口号)。
程控输入/输出
程控输入/输出需要全部数据操作处于处理机执行程序的完全控制之下。因为程序重复地巡查 (检查) 一个输入/输出装置的状态标志,所以有时它被称为巡查,而且它的输入/ 输出操作能与处理器同步。程序不断地巡查一个输入/输出装置的状态,以发现数据是否是已在输入缓冲中或输出装置有没有为接收从来自处理器的数据做好准备。 如果状态显示 " 已备好 " ,则程序将执行一条数据传输指令以完成该输入/输出操作;否则,输入/输出装置的忙碌状态将会强迫程序在一个忙碌等待回路中循环,直到状态变成“已备好”为止。这样一个如此不断地巡查“数据已备好“状态 (对于输入) 或巡查“设备已备好“状态 (对于输出),它形成程控输入/输出的典型程序结构。正是这个浪费时间的忙碌等待回路消耗处理机时间,而造成程控输入/输出效率很低。处理器必须连续的介入整个的输入/输出过程当中。在这一时间间隔内,处理器不能够运行任何的有用计算, 而仅服务于单独一个输入/输出装置。对于某些慢速输入/输出装置,
这一忙碌等待回路的时间可能很长,足够处理机在输入/输出事件发生之前,运行数以百万计指令,如在键盘上的一次按键动作。
上面叙述的程控输入/输出操作模式是以程序的忙碌等待回路为特征的, 在它运行时处理器花费时间巡查一个输入/输出装置。因为处理器专注于一个单一的作业,这种程控输入/输出模式被称为专注式巡查或回旋式巡查。虽然专注式巡查十分低效, 但是有时它是必需的,甚至是不可避免的。在一个特别的情形中,如果一件紧急的事件需要没有延迟立即响应,则用一台专门的计算机做专注式巡查可能是最好的处理方法。一旦预期的事件发生, 处理器可以立刻反应。举例来说, 某些实时系统 (如雷达回波处理系统) 需要对收入的数据极快的反应,甚至是一次中断反应都嫌太慢。在这样的环境之下,只有专注式巡查回路才足够应付。
程控输入/输出的另一个操作模式叫做间歇式巡查或定时巡查。在这一个模式中,处理器可在有规则的(预期的或事先规划的)时间间隔巡查设备。这种设备在许多嵌入式系统中可以看到,其中一台专用计算机用于过程控制、数据采集、环境监测、流量计数等。这些设备量测、收集或记录数据,通常是按照有规则的时间表进行周期性的巡查,其规划由应用对象的需要决定。这种间歇式巡查方法可以有助于节省回旋式巡查所浪费的时间,并且避免中断处理的复杂性。然而应该注意,间歇式巡查可能不适用某些特别的情形, 只有一个装置被巡查而正确的
巡查又一定要借助一个由中断驱动的时钟才能得到。在这种情况使用定时巡查只能是简单的交替一次又一次中断需求。
中断驱动输入/输出
中断驱动输入/输出是一种能避免程控输入 / 输出特有的低效忙碌等待回路的方法。当输入 / 输出设备忙于它的输入输出作业时,处理机不是等待,而是可以运行其他的程序。当输入/输出设备完成它的作业而使其状态变为“已好”
时,它将向处理机发出一个中断请求,要求CPU的服务。作为响应,处理机挂起它正在做的任何工作,以便照顾该输入 / 输出设备的需要。
为了响应中断请求, 处理器将会首先为正在运行中的程序保存好程序计数器和状态计数器的内容,然后转移控制到对应的中断服务程序,以执行要求的输入/输出操作。当中断服务程序已经执行完毕时,如果没有更多的中断请求在等待,处理器将恢复状态寄存器和程序计数器的内容,恢复执行原先被中断的程序。处理器的硬件应该在每条指令执行结束时 检查中断请求信号。如果有多个装置同时发行它们的中断请求,处理器必须利用某些方法选择哪一个首先服务, 然后再根据优先权的次序逐个的服务所有其他的中断请求。只有当所有的中断请求都已得到服务,CPU 才返回被中断的用户程序。这样,处理器能并发的服务于多个输入/输出装置,而且用较多的时间做有用的工作, 而不去运行一个忙碌等待回路为单 个装置服务。因此,中断驱动输入 / 输出在处理慢速和中速输入 / 输出/设备方面是很有效的。此外,中断的观念可以被推广到处理任何由硬件或软件从内部或外部产生的事件。这一普遍性问题称为异常事件处理。
如果多个中断请求有不同的设备同时发出,处理器应该有某种方法识别中断来源而且按照某种策略(典型的是按优先权)处理它们的中断请求。现时只能有一个带最高优先权的请求可以得到服务, 所有其它的请求都放入一个候补等待的队伍之内。在中断服务程序执行服务完毕,处理器应该搜索等待的队列,找出所有正在等待中的旧的或新的中断请求, 并按照优先权逐个继续为它们服务,直到等待的队伍变空为止。 只有当所有等待着的中断请求都已经得到服务,才会唤回被中断的用户程序。 虽然这一个情形包含了多个中断请求, 但是它仍然是一个被单一化的情形。假定:所有的中断服务程序一旦被处理器一个接一个的启动,它们便必须完成而不再由中断或所谓抢占发生。满足这一假设的中断过程称为非抢占中断。 在真实的环境中,中断驱动输入/输出的过程比这个简化过程更为复杂。每个正在处理机中运行的中断服务程序可以被新来的中断请求所抢占(中断),只需它的优先权比现有的优先权高。这一个环境将会引起主程序所
有被要求的中断服务程序之间有一个复杂的相互关系。允许中断服务程序被较高优先权的中断服务程序所强占的中断过程叫做抢占中断。
展开阅读全文