Linux设备驱动程序编程中使用struct inode和struct file传递数据的原因
我正在学习 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 和其他方法最终将能够访问它,而无需经历所有传递使用inode
和file
。
我的问题是,为什么我们不将其设为全局变量呢?
谁能提供一些使用这种方法传递数据的实际例子?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
主要原因是你的驱动程序可以管理多个设备。例如,您可以创建 (
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 differentscull_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.
线程安全!如果两个线程/进程同时使用驱动程序怎么办?
Thread-safety! What if two threads/processes are using the driver simultaneously?
您还可以避免使用私有数据来存储您的实际设备,如果您需要私有数据用于其他用途,这是一种常见的选择。在这种情况下,您需要在 scull_read 例程中检索次设备号。它会是这样的:
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:
我不认为这是一个安全问题。它更像是一种设计选择。如果我没记错的话,线程安全是通过上下移动 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.
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