8

我正在学习 Linux 设备驱动程序,并被困在主要的、次要的数字上。到目前为止,我所拥有的是:

  • 通过文件系统中的名称访问设备。这些名称被称为特殊文件或设备文件或文件系统的 inode。

  • 并且每个设备文件都与捆绑到一个dev_t类型中的 MAJOR 和 MINOR 编号相关联。

  • 这些编号由函数分配给设备register_chrdev_region

有些问题还困扰着我……

  1. 当我们初始化设备时,该fops结构是否链接到f_ops设备文件的文件结构字段cdev_init(&c_dev, &fops);
  2. 调用如何open("/dev/mydev", O_RONLY);实际调用open() 驱动程序的功能。此处是否出现数字以查找设备驱动程序的实际写入方法,如果是如何?
  3. 数字,major 用于标识设备驱动程序,minor 用于设备文件。当我们对设备文件等进行操作时,这个数字的实际作用是什么open() read() write()
4

1 回答 1

11

我认为故事应该从你打字时发生的事情开始:

mknod /dev/c83 c 8 3

它将调用 ext2_mknod("/dev", "c83", CHAR, DEV(8, 3)),大多数文件系统将 mknod 实现为 init_special_inode 的包装器:

void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
        inode->i_mode = mode;
        if (S_ISCHR(mode)) {
                inode->i_fop = &def_chr_fops;
                inode->i_rdev = rdev;
        } else if (S_ISBLK(mode)) {
                inode->i_fop = &def_blk_fops;
                inode->i_rdev = rdev;
        } else if (S_ISFIFO(mode))
                inode->i_fop = &def_fifo_fops;
        else if (S_ISSOCK(mode))
                inode->i_fop = &bad_sock_fops;
        else
                printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n",
                       mode);
}

当你最终调用 open("/dev/c83") 时,它将进入函数 def_chr_fops.chrdev_open,它将用你在 cdev_init() 中注册的 fops 替换文件 "/dev/c83" 的 fops:

int chrdev_open(struct inode * inode, struct file * filp)
{
    struct cdev *p;
    ...
    p = inode->i_cdev;
    ...
    filp->f_op = fops_get(p->ops);
    ...
    if (filp->f_op->open) {
        lock_kernel();
        ret = filp->f_op->open(inode,filp);
        unlock_kernel();
    }
    ...
    return ret;
 }

之后,每个系统调用(例如读/写/关闭)都直接转到 cdev_init() 中注册的函数指针!

所以,对于你的第一个问题:

  1. 是的,正如您在 chrdev_open() 中看到的那样。
  2. 是的,因为设备的 fops 与 cdev_init 中注册的完全相同
  3. 在 open() 中起着重要作用,因为 open() 使用对来查找正确的设备驱动程序。但在那之后,其他文件操作,例如读/写/关闭(),不再参与,一切都通过在open()中解析的fops中的函数指针。
于 2013-01-29T15:00:19.483 回答