c - Linux 如何将设备文件与设备驱动程序链接起来? open() 系统调用最终会调用设备驱动程序代码吗?

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

我有一个关于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 文件操作表的地址。”这意味着所有 block 设备文件都具有相同的read()/write() 函数,但是用户如何与不同 设备通信?

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

最佳答案

以下适用于开启角色特殊装置。

当文件打开时,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 cdev 中的 ops 指针,该指针由驱动程序为字符设置特殊装置。

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

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

关于c - Linux 如何将设备文件与设备驱动程序链接起来? open() 系统调用最终会调用设备驱动程序代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57773007/

相关文章:

linux - rtmpdump 通过命令行检查状态

linux - 更新 Babun 时权限被拒绝

linux - 检查在/usr/src/kernel-headers-2.6.32-279.el6.i686中查找内核源代码或 header ...配置: error: not found

c - 确定对cgroup任务的写入失败是否是持久性的?

c++ - "const"声明有助于编译器 (GCC) 生成更快的代码吗?

regex - 如何检查一个字符串是否至少包含一个字母字符?

c - 在 Linux 内核中构建模块需要哪些文件/目录?

c - 在哪里可以找到例如 netlink 的源代码?

python - 如何替换Windows中的posix闹钟

c++ - 多维稀疏矩阵压缩