发布时间:2026-07-21阅读(1)
操作系统访问IO设备的过程,经历过很多个层次,就像网络层协议一样,每一层干每一层的事情,每一层又向上层提供接口,操作系统访问IO设备的层次结构如下图所示:

IO结构层次
因此,本篇文章分为5个部分,逐步阐述操作系统访问IO设备的过程
IO设备大致分为块设备,字符设备,网络设备,定时器等,本篇文章主要关注的是块设备,字符设备,网络设备,这些设备是我们程序开发中经常涉及的部分。
块设备:
块设备将数据分隔成多个固定大小的块进行存储,块是数据存储的最小单位,每个块的大小可以为512字节-65536字节,每个块都有唯一的地址,因此块设备是可以寻址的,每次读写块设备的数据时,都是以块为最小单位读取或者写入连续的多个块。
例如磁盘就是块设备,它的块大小通常是512个字节等于磁盘的一个扇区的大小,因此一个扇区就是一个块,磁盘的数据是由很多个扇区构成。
通常块设备可以顺序访问或者随机访问,应用程序访问块设备时,通常不是直接访问的,而是通过文件系统,文件系统对块设备进行统一管理,将块设备的各类细节封装起来,文件系统管理的是逻辑设备即文件,文件系统统一提供read,write,seek等接口间接访问块设备,文件系统将文件名和块设备的每一个块之间的映射关系隐藏起来,因此块设备对于应用程序来说是透明。
当然有些特殊的应用程序例如数据库管理系统可以直接访问块设备,对块设备的每个块采用专用的数据结构进行管理,以达到最佳的读写效率,这些专用的数据结构有B 树,LSVM树等,这些数据结构都有各自的应用场景。
字符设备:
字符设备是不可以存储和不可以寻址的,字符设备每次读入或者写入一个字符,常见的字符设备包括鼠标,键盘,打印机等,操作系统通常会提供一些get或者put的方法来读取或者写入一个字节,通常会有标准库对操作系统提供的get或者put方法进行封装,例如增加了字符缓冲,支持字符流读写,支持按行读,按行写,编辑缓冲数据等。
网络设备:
网络设备通常用于发送或者接受网络数据,这些网络数据通常是网络包的形式,不同于块设备,操作系统会提供专门的网络接口进行网络数据的发送和接受,网络接口通常就是socket,这个Socket是传输层协议的代理,我们通过socket就可以处理网络数据了。
对于Socket它就像一个电源插座,任何电器都可以插入电源插座,一旦插入电源插座就可以通电,因此应用程序也可以用创建一个Socket,Socket分为服务端Socket和客户端Socket,服务端Socket启动后,会一直监听来自客户端Socket的来电,一旦接到来电就可以转给一个接线员,这个接线员也是一个Socket,由它来负责与客户端Socket的通信。
Socket通常支持BIO,NIO,AIO几种模式,不同的操作系统支持的模式不同,通常都支持BIO和NIO,根据不同的应用场景可以选择不同的模式,没有绝对可言。
定时器:
定时器通常分为硬定时器和软定时器。
硬定时器:
硬定时器通常是由晶体震荡器,计数器和存储寄存器组成,当把一块石英晶体适当地切割后,并在它上加上一定的电压后,它就可以非常精确地产生周期性的时钟信号,这些信号的频率可以是几百赫兹,几千赫兹等,这个频率值跟所选的晶体类型有关。
硬定时器的基本原理是这样的:
每个定时器会在存储寄存器设置一个计数值,每次定时器启动时,将这个计数值设置到计数器中,每次晶体震荡后,产生一个时钟信号,该信号被送入到计数器,计数器就减1,直到计数器变为0,那就表示定时器触发了,它会给CPu发送一个时钟中断,CPU接收到这个中断后会进入时钟处理程序。
时钟处理程序会进行一些防止进程时间片超时,进程CPU使用情况记账,维护计算机时间,计算机硬件监控,进程性能数据剖析等工作。
硬件定时器可以分为一次性定时器和永久性定时器,一次性定时器表示定时器触发后后,就自动停止了,永久性定时器则每次定时器触发后,会将存储寄存器中的计数值重新赋值给计数器,然后重新启动定时器,一直运行,直到计算机关闭。
软定时器:
有些高性能的工作需要高频率地执行,例如一个高性能的网络,网络带宽为千兆级别以上,为了保证高效率地输出,每隔12us就要发送一个数据包,如果采用硬定时器,每隔12us产生中断后,会进行一系列的处理,包括进程上下文,流水线,高速缓冲,TLB,MMU等重新切换等,这一繁杂的切换工作需要的时间可能已经接近12us,那么这就意味着从中断开始到真正开始发送数据包,会经过一段时间,这个时间对于一个高性能的网络来说是不能容忍的,因此这种场景可以采用软定时器,软定时器不需要中断,每次发送数据包时,会根据硬定时器 12us设置一个超时时间,每次发送完数据包切换到用户态后,用户程序检查这个超时时间是不是已经过期了,如果过期了就立即发送一个数据包,对于这类高性能的场景,软定时器比较合适,当然如果没有要求那么高的性能要求的话,一般的硬定时器中断足够应付了。
设备控制器:操作系统是不直接操作IO设备,常常是通过设备控制器间接访问IO设备,可以说设备控制器是CPU与IO设备的桥梁,设备控制器可以连接单个设备,也可以同时连接多个设备,如果连接多个设备,设备控制器和设备之间需要增加一个仲裁设备,这个仲裁设备负责仲裁设备控制器要和那个IO设备进行交互。
设备控制器负责的工作如下:
设备控制器提供了4种寄存器即状态寄存器,数据输入寄存器,数据输出寄存器,控制寄存器,操作系统和设备控制器之间的交互就是通过这些设备寄存器,因此它们的交互方式类似于生产者和消费者的关系。
数据输出寄存器:
操作系统可以将CPU寄存器的数据发送到数据输出寄存器,设备控制器得知数据输出寄存器有数据后,就将数据输出寄存器的数据发送给IO设备。
数据输入寄存器:
设备控制器读入IO设备的数据后,存储在数据输入寄存器,然后操作系统读取数据输入寄存器的数据到CPU寄存器中。
状态寄存器:
存储设备相关的状态,例如设备是否已经就绪,数据输入寄存器是不是有数据了等,操作系统可以读取该寄存器的值来查看设备的各类状态。
控制寄存器:
操作系统可以写入控制寄存器从而告知设备控制器执行什么IO操作。
另外,为了协调CPU和IO设备的读写速度差异,设备控制器通常有数据缓冲,用于缓冲从设备读入的数据,或者从操作系统写入的数据,例如操作系统将数据写入到数据输出寄存器后,设备控制器将数据输出寄存器的数据直接写入到数据缓冲,而不是直接发送到IO设备,这个很好理解,因为设备控制器写入数据到IO设备的速度与CPU的发送速度相比差异太大了。
操作系统怎么读写设备寄存器呢,有两种方式
1.IO指令
每个设备寄存器都有一个地址,它与内存的地址不同,这个地址称为IO端口地址,操作系统支持的IO端口地址有65536个即0~64K-1,IO端口地址的范围叫做IO端口空间,内存地址范围叫做内存空间,因此IO端口空间与内存空间是独立的。
假如CPU要读取一个端口地址对应设备寄存器,过程如下:
1.CPU将IO端口地址放到地址总线上,然后在控制总线上设置一个READ信号,此时只是CPU只是要表明要读取某个地址的数据了,至于这个地址来自哪个空间,还需要下一步操作。
2.CPU设备另外一条信号线,设置信号线要访问IO端口空间。
3.所有的设备控制器接收到该信号线后,发现是访问IO端口空间,就会检查地址总线上的地址是不是自己的寄存器的地址,总有一个设备控制器接受这个地址,不是自己的地址设备控制器直接忽略这个信号。
下面表格为PC设备中常见的设备IO端口地址分布图
Copyright © 2024 有趣生活 All Rights Reserve吉ICP备19000289号-5 TXT地图HTML地图XML地图