【问题标题】:How does Linux link device file with device driver? Does open() syscall eventually call device driver code?Linux如何将设备文件与设备驱动程序链接? open() 系统调用最终会调用设备驱动程序代码吗?
【发布时间】:2020-01-06 10:32:24
【问题描述】:

我有一个关于Linux设备文件和驱动的问题,我目前的理解如下:

  1. 当用户在某个设备文件上调用open() 时,内核会在某个时间点向设备文件的inode 询问read()/write() 函数。

    李>
  2. 设备文件是由udev早先创建的,基于/sys文件夹中的设备,这意味着设备文件的inode应该有i_fop字段指向知道如何与之对话的函数设备,例如read/write/mmap/ioctl/poll。这意味着每个设备文件的inode->i_fop 字段应该指向不同的file_operations 结构。

如果是这样,设备驱动程序将提供这些read()/write()函数,可能是完整的file_operations结构,包括read/write/mmap/ioctl等。

现在,ULK 说(在设备文件的open() 系统调用的描述中)“将inode 对象的i_fop 字段设置为def_blk_fopsdef_chr_fops 文件操作表的地址,根据设备文件的类型。"这意味着所有块设备文件都具有相同的read()/write() 函数,但是用户如何与不同的设备通信呢?

我还检查了device_driver 结构,确实没有地方存储文件访问函数,那么open() 系统调用究竟是如何使用特定于设备的驱动程序执行其工作的呢?如果不在device_driver 中,设备特定的操作功能在哪里?

【问题讨论】:

  • "Linux 如何将设备文件与设备驱动程序链接?" - 按主要次要 数字。实际上,任何设备文件都只包含这些数字。只有在打开设备文件时,Linux内核才会检查是否注册了具有该编号的设备,并为该设备调用相应的函数。
  • @Tsyvarev 谢谢,那么device_driver 在这个过程中提供了什么,因为cdev 结构已经有file_operations
  • 如果你查看device_driver structure's definition 你会发现这个结构描述的东西与文件操作完全不同。它有例如probe 将设备与驱动程序绑定的函数。

标签: c linux linux-kernel linux-device-driver device-driver


【解决方案1】:

简短的回答,它知道根据主要和次要数字最终调用哪个开放函数。当您注册您的驱动程序时,您可以提供这些或获取自动生成的,无论是字符、块还是 tty。

使用 udev 或 systemd 或 mdev 还会自动在/dev 下创建设备。在某些情况下,嵌入式发行版(例如 buildroot)和字符设备不会自动发生这种情况,您需要手动进行。我建议查看“Linux Device Drivers, 3rd edition, Chapter 3: Char Drivers”了解更多详情。

【讨论】:

    【解决方案2】:

    以下适用于打开字符特殊设备。

    当文件打开时,inode 对象的i_fop 指针被复制到文件对象的f_op 指针。对于字符特殊设备,这指向def_chr_fopsdef_chr_fops.open 指向chrdev_open,因此在打开任何字符特殊设备时都会调用chrdev_open(inode, filp)

    chrdev_open 查看其已注册的 struct cdev 对象集,这些对象将 inode 的主要/次要编号(组合成 dev_t 编号)映射到特定的已注册 struct cdev。如果找不到匹配的struct cdev,则返回-ENXIO。否则,它将文件对象中的f_op 指针替换为来自struct cdevops 指针,该指针由字符特殊设备的驱动程序设置。

    如果文件对象的f_op->open不为空,则调用它,并由chrdev_open返回其返回值。否则,此字符特殊设备不需要特殊的“打开”处理并返回 0。

    如果chrdev_open 返回0,则文件对象处于“打开”状态,其f_op 指针指向特定于驱动程序的文件操作。 open 系统调用最终会返回一个文件描述符。如果chrdev_open 返回负的errno 值,文件对象将被销毁,open 系统调用将返回-1,errno 将根据chrdev_open 的返回值设置。

    【讨论】:

    • 谢谢。正是我想要的。
    • 一个后续问题。似乎cdev 包含驱动程序代码,cdev_add() 将其注册到cdev_map 内核变量。他们已经将设备文件链接到驱动程序,但是device_driver struct 和driver_register() 函数呢,它们似乎与 sysfs 相关?设备驱动是否需要在驱动初始化代码中同时调用driver_register()(直接或间接)和cdev_add()
    • @QnA 字符设备有不同的方面。驱动程序需要硬件设备,这通常是通过匹配总线上的硬件设备 ID 来实现的,这就是driver_register 的用武之地。在文件访问级别,设备需要一个设备号和一组文件操作,因此有函数可以保留设备号(register_chrdev_regionalloc_chrdev_region__register_chrdev)并将设备号与文件操作关联(cdev_add__register_chrdev)。第三个方面是通过class_createdevice_create在“/dev”中动态创建文件路径。
    猜你喜欢
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多