UNIX/Linux操作系统中的I/O子系统是实现进程与外部设备通信的关键部分。它主要由设备驱动程序来完成,设备驱动程序作为I/O子系统的核心模块,与特定类型的设备一一对应,并控制这类设备的全部实例。根据设备的性质,UNIX系统中的设备大致分为两类:块设备和字符设备。
块设备按块为单位进行数据传输,常见的块设备有硬盘、软盘、磁带、光盘等。块设备的操作是面向块的,通常用于大量数据的存储和备份,其特点是数据传输效率高,但对数据访问的实时性要求较低。字符设备则以单个字节为单位进行数据传输,常见的字符设备包括终端、打印机、绘图仪、调制解调器、网卡等。字符设备的操作是面向字符的,适用于需要即时处理的场景,如键盘输入或打印机输出。
在UNIX/Linux系统中,每个设备都通过设备文件(i节点)来表示,用于标识设备的属性,如设备名和设备类型。系统配置时需要指定系统中存在的设备及其“地址”,即将设备文件与设备驱动程序建立关联。例如,使用mknod命令创建设备文件。
设备驱动程序接口是核心与驱动程序的接口,它包括块设备开关表和字符设备开关表。每种设备类型在开关表中都有多个表项,这些表项在系统调用时根据设备类型引导核心转向适当的驱动程序接口。硬件与驱动程序的接口主要由与机器相关的控制寄存器、操作设备的I/O指令及中断向量组成。当中断发生时,系统识别发出中断的设备并调用相应的中断处理程序。
驱动程序的入口点涉及一系列系统调用,例如open、close、read、write、ioctl等。系统调用使用文件描述符的基本操作流程是,核心根据用户文件描述符的指针找到系统打开文件表项和文件的索引节点,检查文件类型并存取相应的设备开关表,根据用户发起的系统调用来调用开关表中的对应函数。
特别地,对设备文件的系统调用与正规文件的系统调用间存在重要区别。在执行驱动程序时,对设备文件的索引节点不上锁,以避免由于驱动程序中进程的睡眠导致其它进程无限期等待。
系统调用open和close是与设备驱动程序接口的重要部分。open算法的输入是路径名和打开方式,输出是文件描述符。算法首先将路径名转换为索引节点,增加索引节点的引用计数,从索引节点中抽取主设备号和次设备号,然后根据设备类型调用相应的驱动程序入口点函数。close算法用于断开进程与设备的连接,它需要确认设备是否还有其他进程打开,并调用相应的close过程。
对于块设备,系统首先判断设备上是否为已安装的文件系统,如果是,则释放索引节点并返回。若不是,则进行其他操作,如搜索数据缓冲区高速缓冲。字符设备的close过程相对简单,直接调用对应的close过程即可。
通过这些算法和机制,UNIX/Linux操作系统能够高效地管理外部设备的I/O操作,同时确保系统资源得到合理分配和高效使用。理解这些知识点对于系统管理员和开发人员来说非常重要,它们有助于开发和维护高效的系统驱动程序,优化系统的输入输出性能。