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 ?
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.