当前位置: 首页 > 科技观察

一篇文章带你了解Linux的输入输出

时间:2023-03-13 22:39:20 科技观察

总线Intel采用双独立总线(英文:DualIndependentBus,DIB),使用外部前端总线连接主系统内存,内部使用后端总线到一个或多个中央处理器,CPU缓存。CPU中的内存接口直接与系统总线通信,然后系统总线连接到一个I/O桥(I/OBridge)。这个I/O桥在一侧连接到我们的内存总线,让我们的CPU与内存通信;另一方面,它连接到I/O总线以连接I/O设备。在物理层面,我们其实可以把总线看成是一组“电线”。线路一般有五种。数据总线(DataBus):需要处理或需要存储的数据在CPU和RAM之间来回传输。地址总线(AddressBus):用来指定数据存放在RAM(RandomAccessMemory)中的地址。控制总线:将微处理器控制单元(ControlUnit)的信号传输给外围设备,常见的有USBBus和1394Bus。扩展总线:可以连接扩展槽和电脑。本地总线(LocalBus):一种扩展的I/O设备输入输出设备,代替更高速的数据传输,而不仅仅是一个设备。大多数输入和输出设备都有两个组件。第一个是它的接口(Interface),第二个是实际的输入输出设备(ActualI/ODevice)。我们的硬件设备并不是直接连接到总线上与CPU通信,而是通过接口连接到总线上,再通过总线与CPU通信。例如,硬盘驱动器可以分为IDE(集成驱动电子)、SCSI(小型计算机系统接口)、SAS(串行连接SCSI)、SATA(串行ATA)和FC(光纤通道),它们都是内置的-在计算机主板上的接口中。硬件只需要提供相应接口的设备驱动即可。设备控制器接口本身就是一个设备控制器。CPU实际上并不与实际的硬件设备打交道,而是与设备控制器打交道。除了将设备连接到计算机之外,设备控制器还有许多重要任务。随时监控设备状态,实现对设备的控制和运行。设备控制器中存在三种类型的寄存器:状态寄存器(StatusRegister)、命令寄存器(CommandRegister)和数据寄存器(DataRegister)。每个控制寄存器都分配了一个I/O端口,我们可以通过特殊的汇编指令(比如in/out类似的指令)来操作这些寄存器。状态寄存器可以通过检测状态标志位来判断输入或输出操作是否完成。一些设备也有数据缓冲区。如打印机等。内存映射I/O可以为其分配一段内存空间,像读写内存一样读写数据缓冲区。设备控制器还监督I/O设备传输的数据的错误检测。如果在传输过程中发生错误,通常会设置错误检测码并上报给CPU,因此CPU使本次传输的数据无效,并进行新的传输。这确保了正确的数据输入。设备驱动程序用于实现设备对具体设备的管理和操作。要使设备工作,需要访问设备控制器中的各种寄存器。这部分通过编写具体的程序代码来实现程序,这就是“设备驱动程序”。主要功能如下:初始化设备使设备运行并退出服务从设备接收数据并发送回内核从内核发送数据到设备检测并处理设备错误DMA控制器有些设备需要被读取或写入大量数据。如果所有进程都由CPU协调,将占用大量CPU时间,例如磁盘的情况。这类设备需要支持DMA功能,即允许设备自己读写内存,不需要CPU的参与。实现DMA机制需要一个DMA控制器为你协调CPU,如下图所示。CPU只需要给DMA控制器下指令,说要读多少数据,放到内存的某个地方。接下来,DMA控制器会向磁盘控制器发送指令,请求将数据传输到内存中。磁盘驱动程序将磁盘上的数据读取到磁盘控制器的内核缓冲区中,磁盘控制器进行错误检查以确保不会出现读取错误。磁盘控制器、CPU、DMA的寄存器都可以修改。当磁盘控制器从其内部缓冲区中读取数据时,它知道应该将数据写入何处。然后数据通过内存总线写入内存。当写操作完成时,磁盘控制器在总线上向DMA控制器发送一个成功的确认。DMA控制器发送中断通知CPU指令完成,CPU可以直接使用内存中现成的数据。中断控制器硬件的中断控制器,当设备完成任务并向中断控制器触发中断时,中断控制器通知CPU中断已经发生,CPU需要停止当前正在做的事情来处理中断打断。一般过程是,当一个设备驱动程序被初始化时,它必须首先为该设备注册一个中断处理程序。中断时触发的函数是do_IRQ。该函数是中断处理的统一入口点。在这个函数中,我们可以找到设备驱动注册的中断处理函数Handler,然后执行它进行中断处理。磁盘驱动程序的实现在Linux中,设备驱动程序是相关函数的集合。它包含设备服务例程和中断处理程序。设备服务子程序包含所有与设备相关的代码,每个设备服务子程序只处理一种设备或密切相关的设备。它的功能是接受来自设备无关软件的抽象命令并执行它们。在执行请求时,具体操作是根据设备控制器提供给驱动程序的接口(指控制器中的各种寄存器),利用中断机制调用中断服务子程序配合设备完成要求。设备驱动使用结构体file_operations与文件系统连接,即设备的各种操作的入口函数都存在于file_operation中。有些操作对于特定设备来说不是必需的,它的条目被设置为NULL。虽然Linux内核中有许多不同的设备驱动程序,但它们有一些共同的特点:驱动程序属于内核代码,设备驱动程序是内核的一部分。它像内核中的其他代码一样在内核模式下运行。如果驱动程序出现故障,将会对操作系统造成严重的损坏,甚至会导致系统崩溃而导致文件系统损坏和数据丢失。为了向内核提供统一的接口,设备驱动程序必须向Linux内核或其他子系统提供标准接口。例如,终端驱动程序为Linux内核提供文件I/O接口。驱动程序执行是一种内核机制并使用内核服务。设备驱动程序可以使用标准的内核服务,例如内存分配、中断调度和等待队列。可动态加载,大多数Linux设备驱动程序可以在内核模块发出加载请求时加载,并在不再使用时卸载。这允许内核有效地利用系统资源。可配置的Linux设备驱动程序可以挂接到内核中。链接到内核的设备驱动程序在编译内核时是可配置的。这样,linux的输入输出就很清楚了。有许多输入和输出设备的设备制造商。因为设备制造商是复杂多变的,所以设备制造商也是复杂多变的。需要层层屏蔽差异化部分,向上层提供标准化部分,最终在用户态基于文件系统为用户提供统一的接口。