【问题标题】:How does the OS know which device driver to call?操作系统如何知道要调用哪个设备驱动程序?
【发布时间】:2018-07-14 06:51:46
【问题描述】:

我一直在 opening 和 write/reading 文件/设备文件并阅读操作系统,但从未理解设备驱动程序是如何不可避免地被调用的流程。

例如,当我们对stdout 执行write 时,即fd=1
当我执行write 时,我知道操作系统会为这个已经打开的特定设备文件调用设备驱动程序,但我不明白我们如何获得设备驱动程序本身。


  1. 首先创建设备文件(即stdout)需要什么?安装?内核模块加载?

  2. (跟进 [1])因此,如果我有一个外围设备,例如连接到我的计算机的单个 LED 灯,并且已经安装了 LED 的正确设备驱动程序,并且在 /dev/singleled 中创建了设备文件,当我将open 呼叫/dev/singleled 时会发生什么?

(具体)

  • 当我向它调用write 时,操作系统如何知道为该设备文件调用哪个设备驱动程序?
  • 当我们对此设备文件执行open 时,我们是否将信息存储在文件描述符中?

我真的很想了解这个设置是如何创建的。
提前感谢大家

【问题讨论】:

  • 我知道这是一个很长的问题,只要有人可以为我指出正确的方向以了解我所问问题的整体情况,我就可以接受反对票跨度>

标签: linux linux-kernel operating-system linux-device-driver


【解决方案1】:

在非常简短的概述术语中,设备节点由主要和次要编号标识,您可以使用ls -l 之类的命令查看它们,并且需要将其传递给mknod 之类的命令,如果从用户空间创建它们。

在内核方面,驱动程序可以为一系列这些数字注册自己。

然后问题就归结为管理一个中等大小的关联数据表,并使用它来查找适当的驱动程序和注册的方法来处理用户空间调用。

您还提到了 LED,但它们通常被处理为 sysfs 节点,即 /sys/class/LED/xxx,这是一个独特的接口,通过匹配名称而不是主要/次要数字来运行。

您可能会发现实际查看一些设备很有帮助,它们都作为/dev/sys 中的节点以及相关的内核代码存在。为解释这些概念而编写的示例/教程驱动程序可能是最清晰的。

【讨论】:

    【解决方案2】:

    嵌入式系统(我工作的地方)领域,操作系统内核通过读取设备树知道要调用哪个设备驱动程序。阅读here,了解我在说什么。

    但是,更准确地说,设备树(即描述操作系统将运行的硬件的文件)是在引导时读取的。因此,操作系统读取它,将实例化正确的驱动程序。在设备树的 compatible 字段中,有确切的 key-word 必须与驱动程序的关键字匹配。

    例如,假设您有一个带有以下节点的设备树:

      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 repository folder 中,您可以找到一个设备驱动模块,通过读取设备树的compatible 字段,可以设法打开它。在同一个文件夹中,有源 C 文件来测试驱动程序打开和关闭它。你可以通过C代码了解openclose被调用时会发生什么等等。

    【讨论】:

    • 并非一切都是设备树。
    • 其实这并没有回答问题,这是关于/dev中的设备文件和驱动程序之间的链接:内核如何处理这个链接?这里的答案更多是关于设备实例和驱动程序之间的匹配(在/dev 中可能没有任何文件)在设备树的非常狭窄的情况下(例如排除所有即插即用)世界:PCI、USB、火线……)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-19
    • 2018-03-19
    • 2020-01-06
    • 1970-01-01
    • 2023-03-06
    • 2020-11-28
    相关资源
    最近更新 更多