操作系统如何知道调用哪个设备驱动程序?

4
我一直在进行文件/设备文件的打开和读写操作,并学习操作系统,但从未理解设备驱动程序如何被调用的流程。
例如,当我们向stdout写入内容时,即fd = 1。当我执行write操作时,我知道操作系统会调用已经打开的特定设备文件的设备驱动程序,但我不明白是如何找到设备驱动程序本身的。
1. 在创建设备文件(比如stdout)之前需要什么?装载?内核模块加载? 2. (针对问题1的后续问题)如果我有一个外围设备,例如连接到计算机上的单个LED灯,已经安装了正确的LED设备驱动程序并创建了设备文件/dev/singleled,在调用open来打开/dev/singleled时会发生什么?
具体来说: - 当我向此设备文件执行write操作时,操作系统如何知道要调用哪个设备驱动程序? - 在对此设备文件执行open操作时,我们是否会在文件描述符中存储信息?
我真的很想理解这个设置。谢谢大家!

我知道这是一个很长的问题,如果有人能指引我正确方向,让我看到我所问问题的整体情况,我愿意接受负评。 - Seoul
2个回答

2
在非常简单的概述术语中,设备节点由主要和次要编号标识,您可以使用类似于“ls -l”命令查看这些编号,并且如果从用户空间创建它们,则需要将它们传递给类似于“mknod”的命令。
在内核方面,驱动程序可以为这些数字范围注册自己。
然后问题就缩小到管理一张适度大小的关联数据表并使用它来查找适当的驱动程序和方法以处理用户空间调用。
您还提到了LED,但是通常将它们作为sysfs节点处理,即/ sys / class / LED / xxx,这是一个不同的接口,通过匹配名称而不是主/次要编号来操作。
您可能会发现实际查看一些设备,包括它们在/dev或/sys中作为节点的存在以及相关的内核代码,会很有帮助。编写用于解释这些概念的示例/教程驱动程序可能是最清晰的选择。

0
在我所从事的嵌入式系统领域中,操作系统内核通过读取“设备树”来知道调用哪个设备驱动程序。点击这里了解更多相关信息。
然而,更准确地说,设备树(描述操作系统运行硬件的文件)是在启动时读取的。因此,操作系统会读取它并实例化正确的驱动程序。在设备树的“compatible”字段中,必须与驱动程序的关键字匹配。
例如,假设您有一个包含以下节点的设备树:
  ps7_axi_interconnect_0: axi@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "xlnx,ps7-axi-interconnect-1.00.a", "simple-bus";
ranges ;
gic: interrupt-controller@f8f01000 {
  #interrupt-cells = < 3 >;
  compatible = "arm,cortex-a9-gic";
  interrupt-controller ;
  reg = < 0xf8f01000 0x1000  >,< 0xf8f00100 0x100  >;
} ;
pl310: pl310-controller@f8f02000 {
  arm,data-latency = < 3 2 2 >;
  arm,tag-latency = < 2 2 2 >;
  cache-level = < 2 >;
  cache-unified ;
  compatible = "arm,pl310-cache";
  interrupts = < 0 34 4 >;
  reg = < 0xf8f02000 0x1000 >;
} ;

  [ ... more items ... ]

xillybus_0: xillybus@50000000 {
  compatible = "xlnx,xillybus-1.00.a";
  reg = < 0x50000000 0x1000 >;
  interrupts = < 0 59 1 >;
  interrupt-parent = <&gic>;
  xlnx,max-burst-len = <0x10>;
  xlnx,native-data-width = <0x20>;
  xlnx,slv-awidth = <0x20>;
  xlnx,slv-dwidth = <0x20>;
  xlnx,use-wstrb = <0x1>;
} ;

} ;

请注意字段compatible。 现在,将使用此节点的驱动程序必须具有类似于以下内容:

static struct of_device_id xillybus_of_match[] __devinitdata = {
  { .compatible = "xlnx,xillybus-1.00.a", },
  {}
};

MODULE_DEVICE_TABLE(of, xillybus_of_match);
/********something else*******/
static struct platform_driver xillybus_platform_driver = {
  .probe = xilly_drv_probe,
  .remove = xilly_drv_remove,
  .driver = {
    .name = "xillybus",
    .owner = THIS_MODULE,
    .of_match_table = xillybus_of_match,
  },
};

为了更好地理解正在发生的事情,请参考this简单教程。希望这能有所帮助。
关于LED示例
在这个git存储库文件夹中,您可以找到一个设备驱动程序模块,它可以通过读取设备树的compatible字段来管理其开启和关闭。在同一文件夹中,还有源C文件来测试驱动程序的开启和关闭。通过阅读C代码,您可以了解在调用openclose时发生了什么等信息。

2
不是所有的东西都是设备树。 - 0andriy
1
实际上,这并没有回答问题,问题是关于/dev中的设备文件和驱动程序之间的链接:内核如何处理这个链接? 这里的答案更多地涉及设备实例和驱动程序之间的匹配(可能没有任何在/dev中的文件),在设备树的非常狭窄的情况下(例如,排除了所有的即插即用设备:PCI、USB、FireWire等)。 - Federico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接