[英]Reason to pass data using struct inode and struct file in Linux device driver programming
我正在学习Linux设备驱动程序的第3.5章,第3版 。 本节介绍一种方法,用于检索我们自己在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
将传递给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 */
}
直到我意识到,我们已经有了这似乎没什么问题struct scull_dev *dev
在初始化过程中scull_setup_cdev
这里 。
我很困惑,因为我认为我们可以使struct scull_dev *dev
成为一个全局变量,然后scull_read
和其他方法最终可以访问它而无需使用inode
和file
进行所有传递。
我的问题是,为什么我们不把它变成一个全局变量?
任何人都可以提供一些使用此方法传递数据的实际示例吗?
主要原因是您的驱动程序可以管理多个设备。 例如,你可以创建( mknod
)几个设备/dev/scull1
, /dev/scull2
, /dev/scull3
......然后每个设备将有一个scull_dev
关联的不同scull_dev
。
使用全局变量,您只能使用一个变量。 即使您的驱动程序仅支持一个这样的设备,也没有理由不设计代码未来证明。
线程安全! 如果两个线程/进程同时使用驱动程序怎么办?
我不认为这是一个安全问题。 它更像是一种设计选择。 如果我没有弄错的话,通过scull_dev中的信号量向下和向上来实现线程安全性。 如果深入研究代码,可以看到打开,读取,写入所有使用过的down_interruptible()。
我想作者1)认为直接访问scull_dev并不好看2)想告诉我们如何使用private_data。 通过将scull_dev指向结构文件,其指针被发送到每个操作,每个操作都可以在不使用全局变量的情况下访问它。
scull驱动程序由4个minors实现,每个minors都有一个单独的scull_dev,每个scull_dev都嵌入了“struct cdev”。 现在让我们说User已经从/ dev / scull0打开了scull0。 在open()函数中,您需要指向正确的scull_dev结构。 scull_dev结构是动态分配的。
你可以在这里看到完整的实现https://github.com/mharsch/ldd3-samples/blob/master/scull/main.c#L450
您还可以避免使用私有数据来存储您的实际设备,如果您需要私有数据用于不同的设置,这是一种常见的选择。 在这种情况下,您需要在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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.