Linux设备驱动程序编程中使用struct inode和struct file传递数据的原因

发布于 2024-12-04 00:57:56 字数 1205 浏览 1 评论 0原文

我正在学习 Linux 设备驱动程序,第三版 的第 3.5 章。本节介绍一种在 open 函数中从 struct inode *inode 检索我们自己定义的自定义结构的方法:

int scull_open(struct inode *inode, struct file *filp)
{
    struct scull_dev *dev;

    dev = container_of(inode->i_cdev, struct scull_dev, cdev);
    filp->private_data = dev; /* for other methods */

    }
    return 0;          
}

根据我的理解,当设备打开时,struct inode *inode代表设备的 code> 被传递到 scull_open。然后,提取自定义结构dev并将其传递给filp->private_data,以便其他方法(例如scull_read)可以使用它:

ssize_t scull_read(struct file *filp, char _ _user *buf, size_t count,
                loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data; 
    /* other codes that uses *dev   */
}

这似乎对我来说很好,直到我意识到在 scull_setup_cdev 初始化期间我们已经有了一个 struct scull_dev *dev 此处

我很困惑,因为我认为我们可以将 struct scull_dev *dev 设为全局变量,然后 scull_read 和其他方法最终将能够访问它,而无需经历所有传递使用inodefile

我的问题是,为什么我们不将其设为全局变量呢?

谁能提供一些使用这种方法传递数据的实际例子?

I'm studying Chapter 3.5 of Linux Device Drivers, 3rd edition. This section introduces a method to retrieve a custom structure we defined ourselves from struct inode *inode in the open function:

int scull_open(struct inode *inode, struct file *filp)
{
    struct scull_dev *dev;

    dev = container_of(inode->i_cdev, struct scull_dev, cdev);
    filp->private_data = dev; /* for other methods */

    }
    return 0;          
}

From my understanding, while the device is opened, the struct inode *inode representing the device is passed to scull_open. Then, the custom structure dev is extracted and passed to filp->private_data so that other methods such as scull_read can use it:

ssize_t scull_read(struct file *filp, char _ _user *buf, size_t count,
                loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data; 
    /* other codes that uses *dev   */
}

This seems fine to me until I realized that we already had a struct scull_dev *dev during initialization in scull_setup_cdev here.

I'm rather confused since I thought we can make struct scull_dev *dev a global variable, then scull_read and other methods will eventually have access to it without going through all the passing using inode and file.

My question is, why don't we just make it a global variable?

Can anyone provide some practical examples of using this method to pass data ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

榆西 2024-12-11 00:57:56

主要原因是你的驱动程序可以管理多个设备。例如,您可以创建 (mknod) 多个设备 /dev/scull1/dev/scull2/dev/scull3< /code>...然后每个都将有一个与之关联的不同的scull_dev

对于全局变量,您只能使用一个变量。即使您的驱动程序仅支持一种此类设备,也没有理由不设计面向未来的代码。

The main reason is so that your driver can manage more than one device. For example, you can create (mknod) several devices /dev/scull1, /dev/scull2, /dev/scull3... and then each of these will have a different scull_dev associated with it.

With a global variable you are limited to one. And even if your driver only supports one such device, there is little reason not to design the code future proof.

就是爱搞怪 2024-12-11 00:57:56

线程安全!如果两个线程/进程同时使用驱动程序怎么办?

Thread-safety! What if two threads/processes are using the driver simultaneously?

稀香 2024-12-11 00:57:56

您还可以避免使用私有数据来存储您的实际设备,如果您需要私有数据用于其他用途,这是一种常见的选择。在这种情况下,您需要在 scull_read 例程中检索次设备号。它会是这样的:

ssize_t scull_read( struct file *filp,
                     char __user* buf,
                     size_t count,
                    loff_t * f_pos ) {

    int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
    printk( "reading on minor number %d\n", minor);
    /* use dev[minor] in ur code */
    return 0;
 }

You can also avoid using the private data to store your actual device, which is a common choice if you need private data for something different. In that case you will need to retrieve the minor number in the scull_read routine. It will be something like that:

ssize_t scull_read( struct file *filp,
                     char __user* buf,
                     size_t count,
                    loff_t * f_pos ) {

    int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
    printk( "reading on minor number %d\n", minor);
    /* use dev[minor] in ur code */
    return 0;
 }
有深☉意 2024-12-11 00:57:56

我不认为这是一个安全问题。它更像是一种设计选择。如果我没记错的话,线程安全是通过上下移动 scull_dev 中的信号量来实现的。如果你深入研究代码,你可以看到open、read、write都使用了down_interruptible()。

我猜作者 1)认为直接访问 scull_dev 看起来不太好 2)想向我们展示如何使用 private_data。通过将指向 scull_dev 的点放在 struct file 中,并将其指针发送给每个操作,每个操作都可以访问它,而无需使用全局变量。

I donot think it is a thead-safety issue. It is more like a design choice. If I am not mistaken, thread-safety is achieved by down and up the semaphore in scull_dev. If you dig into the code, you can see open, read, write all used down_interruptible().

I guess the author 1) believes accessing scull_dev directly doesnot look good 2) wants to show us how to use private_data. By putting the point to scull_dev in struct file whose pointer is sent to each operation, each operation can access it without using global variable.

海的爱人是光 2024-12-11 00:57:56

scull驱动由4个minor实现,每个minor都有一个单独的scull_dev,每个scull_dev都嵌入了“struct cdev”。现在假设用户已从 /dev/scull0 打开 scull0。在 open() 函数中,您需要指向正确的 scull_dev 结构。 scull_dev 结构是动态分配的。

您可以在此处查看完整的实现
https://github.com/mharsch/ldd3-样本/blob/master/scull/main.c#L450

The scull driver is implemented with 4 minors, each of which has a separate scull_dev, each scull_dev has "struct cdev" embedded in it. Now Let's say User has opened scull0 from /dev/scull0. In the open() function you need to point to the correct scull_dev structure. The scull_dev structures are dynamically allocated.

You can see the full implementation here
https://github.com/mharsch/ldd3-samples/blob/master/scull/main.c#L450

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文