无论是块设备还是字符设备,都是属于IO硬件,在整个硬件到软件层之前的了解,有助于我们理解。
I/O设备
块设备
是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区。
这些数据片就称作块。最常见的块设备是硬盘,除此以外,还有软盘驱动器、CD-ROM驱动器和闪存等等许多其他块设备。注意,它们都是以安装文件系统的方式使用的——这也是块设备的一般访问方式。
字符设备
另一种基本的设备类型是字符设备。是一个顺序的数据流设备,对这种设备的读写是按字符进行的,而且这些字符是连续地形成一个数据流。他不具备缓冲区,所以对这种设备的读写是实时的。
字符设备按照字符流的方式被有序访问,像串口和键盘就都属于字符设备。
如果一个硬件设备是以字符流的方式被访问的话,那就应该将它归于字符设备;反过来,如果一个设备是随机(无序的)访问的,那么它就属于块设备。
设备控制器
无论是块设备还是字符设备,都是硬件的一部分,为了能把这些如 键盘,磁盘盘等的输入输出设备统一管理,就引出了设备控制器的概念,它也是硬件层的部分。
那设备控制器有什么组成,有什么功能呢?
控制器是有三类寄存器,它们分别是状态寄存器(Status Register)、 命令寄存器(Command Register)以及数据寄存器(Data Register)
内存映射
每个控制器有几个寄存器用来与CPU通信,通过写入这些寄存器操作系统可以命令设备发送数据,接收数据,开启或关闭,或者其他操作。通过读取这些寄存器,操作系统可以了解设备的状态,是否准备好接受一个新的命令。
和字符设备不同,块设备,比如我们知道的硬盘,它通常传输的数据量会非常大,于是控制器设立了一个可读写的数据缓冲区。
- CPU 写入数据到控制器的缓冲区时,当缓冲区的数据囤够了一部分,才会发给设备。
- CPU 从控制器的缓冲区读取数据时,也需要缓冲区囤够了一部分,才拷贝到内存。
这个数据缓冲区和寄存器同层。
接下来,我们又了解到,为了满足外设的IO请求或者CPU通知了设备的一个指令,当完成的时候,怎么通知CPU呢?
存在两个可选方法:
在第一个方法,每个控制寄存器被分配一个I/O端口号,这个是一个8/16位的整数。所有I/O端口形成I/O端口空间,并且受到保护使得普通的用户程序不能访问。CPU可以通过特殊的I/O指令读取控制寄存器的内容并存入CPU寄存器REG中。
第二个方法是PDP-11引入的,它将所有控制寄存器映射到内存空间,每个控制寄存器被分配唯一的内存地址,这样的系统称为内存映射I/O。
直接存储器存取
我们就有外部中断,这是通过中断控制器实现。,中断有两种,一种软中断,例如代码调用 INT
指令触发,一种是硬件中断,就是硬件通过中断控制器触发的。
但中断的方式对于频繁读写数据的磁盘,并不友好,这样 CPU 容易经常被打断,会占用 CPU 大量的时间。对于这一类设备的问题的解决方法是使用 DMA(Direct Memory Access) 功能,它可以使得设备在 CPU 不参与的情况下,能够自行完成把设备 I/O 数据放入到内存。那要实现 DMA 功能要有 「DMA 控制器」硬件的支持。
总结
I/O硬件提到了,再往上就进入了I/O软件,比如为了屏蔽不同设备控制器的差异,Linux系统中,设备驱动程序就发挥作用了。
设备控制器不属于操作系统范畴,它是属于硬件,而设备驱动程序属于操作系统的一部分,操作系统的内核代码可以像本地调用代码一样使用设备驱动程序的接口,而设备驱动程序是面向设备控制器的代码,它发出操控设备控制器的指令后,才可以操作设备控制器。
这只是简单的举例。