Operating system 驱动程序的工作方式(例如PCIe和USB)

Operating system 驱动程序的工作方式(例如PCIe和USB),operating-system,driver,Operating System,Driver,我很好奇司机一般是如何工作的。我确实了解基本概念以及单个驱动程序的操作方式。我感到困惑的是,当涉及多个驱动程序时,它们是如何工作的 让我通过一个例子来解释我的问题: 假设我在硬件中有一个PCIe和USB接口。主机的主要接口(驱动程序、操作系统和应用程序所在的位置)是PCIe。主机可通过PCIe访问USB接口 所以,在这种情况下,我会有PCIe驱动程序以及USB驱动程序。 当应用程序必须通过USB传输数据时,应用程序将调用系统/操作系统调用。这将最终降落在USB驱动程序。 这是正确的吗 USB驱动

我很好奇司机一般是如何工作的。我确实了解基本概念以及单个驱动程序的操作方式。我感到困惑的是,当涉及多个驱动程序时,它们是如何工作的

让我通过一个例子来解释我的问题:

假设我在硬件中有一个PCIe和USB接口。主机的主要接口(驱动程序、操作系统和应用程序所在的位置)是PCIe。主机可通过PCIe访问USB接口

所以,在这种情况下,我会有PCIe驱动程序以及USB驱动程序。 当应用程序必须通过USB传输数据时,应用程序将调用系统/操作系统调用。这将最终降落在USB驱动程序。 这是正确的吗

USB驱动程序完成处理后,必须调用PCIe调用。是谁干的?是操作系统还是USB驱动程序本身? 我认为,这将是操作系统,否则它将打破基本的模块化哲学。但驱动程序调用操作系统似乎是违反直觉的,因为我总是假设流程是从应用程序到操作系统再到驱动程序和硬件


有人能解释一下这个话题吗?

就像在用户空间代码中一样,在内核领域存在用于访问各种类型硬件的标准化API(具体使用情况因操作系统而异)。因此,对于一个设备驱动程序来说,通过这些标准化的API访问另一个设备的驱动程序并不是一件容易的事。(警告:USB是一个非常复杂的协议,许多细节都被掩盖了,以缩短长文章)

最初的问题集中在PCIe到USB卡上。在这个例子中,我认为有三层驱动程序是很有帮助的。第一层是PCIe总线控制器驱动程序,它控制PCIe总线特定功能,例如为PCIe设备映射MMIO并支持来自这些PCIe设备的中断。第二层是USB主机控制器层,它提供发布标准化USB事务的功能。最后,USB设备驱动程序(如USB驱动程序键盘)位于堆栈顶部,使用标准化USB事务实现特定USB外围设备的功能。来自键盘驱动程序的调用将调用USB主机控制器驱动程序中的功能,而USB主机控制器驱动程序甚至可能调用PCIe驱动程序。所有这些都是在内核空间中完成的,即使使用了许多单独的驱动程序

大多数PCIe设备通过MMIO访问与CPU进行大部分通信,这表现为对处理器的内存读/写。一般来说,执行从PCIe到CPU的MMIO数据传输不需要特定的驱动程序功能(尽管可能有一些简单的访问功能来执行endian校正或处理缓存问题)

USB主机控制器驱动程序很有趣,因为它们符合一个标准(如XHCI,USB 3.0标准,我将在本例中使用),该标准规定了标准的设备内存映射和行为。因此,通常有一些特定于芯片的驱动程序对USB主机控制器设备执行非标准初始化。此外,这些特定于芯片的驱动程序将检索XHCI标准化MMIO区域的位置,并提供一种从XHCI控制器接收中断的方法(在本例中为PCIe中断)

接下来,这个标准化的内存区域和中断机制被传递给一个通用的XHCI主机控制器驱动程序。通用XHCI代码不关心设备是否为PCIe,只关心它是否通过了遵循XHCI标准的内存区域,以及它是否接收到了正确的中断。XHCI驱动程序提供了通用USB传输功能,而USB键盘设备又可以使用这些功能来启动USB事务


在大多数情况下,XHCI驱动程序只是对传入的MMIO区域执行读/写操作。这允许相同的通用XHCI代码服务于宽阵列USB主机控制器,其中许多不是PCIe设备。从而有效地允许XHCI驱动程序抽象出实现USB控制器的底层硬件。因此,对于原始问题提出的示例,USB主机控制器标准旨在隐藏底层硬件机制,以实现更模块化的USB驱动程序系统。

Google“interrupts”不幸的是,这是高度特定于系统的。