Intel采用双独立总线(英语:Dual Independent Bus,DIB),使用外部的前端总线到主系统存储器,和内部的后端总线于一个或多个中央处理器、CPU缓存间。CPU 里面的内存接口,直接和系统总线通信,然后系统总线再接入一个 I/O 桥接器(I/O Bridge)。这个 I/O 桥接器,一边接入了我们的内存总线,使得我们的 CPU 和内存通信;另一边呢,又接入了一个 I/O 总线,用来连接 I/O 设备。

在物理层面,其实我们完全可以把总线看作一组“电线”。一般有五类线路。
输入输出设备,并不只是一个设备。大部分的输入输出设备,都有两个组成部分。第一个是它的接口(Interface),第二个才是实际的 I/O 设备(Actual I/O Device)。我们的硬件设备并不是直接接入到总线上和 CPU 通信的,而是通过接口,用接口连接到总线上,再通过总线和 CPU 通信。比如可以把硬盘分为 IDE(Integrated Drive Electronics)、SCSI(Small Computer System Interface) 、SAS(Serial Attached SCSI) 、SATA(Serial ATA) 、FC(Fibre Channel)都是计算机主板上内置的各个接口。硬件只需要提供对应接口的设备驱动程序。
接口本身就是设备控制器。CPU 其实不是和实际的硬件设备打交道,而是和设备控制器打交道。设备控制器除了要将设备与计算机连接外,还有很多重要任务。
用于实现设备对具体设备的管理与操作。要让设备工作,必选访问设备控制器中的各种寄存器,这部分通过编写特定的程序代码来实现程序,就是“设备驱动程序”。主要有以下功能:
有的设备需要读取或者写入大量数据。如果所有过程都让 CPU 协调的话,就需要占用 CPU 大量的时间,比方说,磁盘就是这样的。这种类型的设备需要支持 DMA 功能,也就是说,允许设备在 CPU 不参与的情况下,能够自行完成对内存的读写。实现 DMA 机制需要有个 DMA 控制器帮你的 CPU 来做协调,就像下面这个图中显示的一样。

硬件的中断控制器,当设备完成任务后触发中断到中断控制器,中断控制器就通知 CPU,一个中断产生了,CPU 需要停下当前手里的事情来处理中断。一般的流程是,一个设备驱动程序初始化的时候,要先注册一个该设备的中断处理函数。中断的时候,触发的函数是 do_IRQ。这个函数是中断处理的统一入口。在这个函数里面,我们可以找到设备驱动程序注册的中断处理函数 Handler,然后执行它进行中断处理。

在Linux中,设备驱动程序是一组相关函数的集合。它包含设备服务子程序和中断处理程序。设备服务子程序包含了所有与设备相关的代码,每个设备服务子程序只处理一种设备或者紧密相关的设备。其功能就是从与设备无关的软件中接受抽象的命令并执行之。当执行一条请求时,具体操作是根据设备控制器对驱动程序提供的接口(指的是控制器中的各种寄存器),并利用中断机制去调用中断服务子程序配合设备来完成这个请求。设备驱动程序利用结构 file_operations 与文件系统联系起来,即设备的各种操作的入口函数存在file_operation中。对于特定的设备来说有一些操作是不必要的,其入口置为NULL。

Linux 内核中虽存在许多不同的设备驱动程序但它们具有一些共同的特性:
输入输出设备的设备厂商很多。因为设备厂商复杂多变,设备厂商也同样复杂多变,需要层层屏蔽差异化的部分,给上层提供标准化的部分,最终到用户态,给用户提供了基于文件系统的统一的接口。
