Currently, I am learning Linux device drivers. And got stuck over how opening a device file works ?
What I got until now...
Consider the a simple code that opens a normal file..
#incldue<stdio.h>
int main() {
FILE fp;
char buffer[20];
fp = fopen(/home/yoggi/foo.txt, "r");
fread(buffer, 5, 1, fp);
}
In above program, The fopen(), c-library function, is a wrapper function to the system call open(), which intern calls sys_open() or file_open() in VFS layer function. As linux supports a number of file system, virtual file system then transfer the control to actual file system handler to the opening that file.
1) How does virtual file system(VFS) get to know on which file system the
underline file resides?
2) How does it then calls the file_open or open function of that particular
filesystem to open file.
In case of device drivers similar things happens. Suppose a simple device driver.
#include <linux/module.h>
// othher includes...
static dev_t first; // Global variable for the first device number
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class
static int my_open(struct inode *i, struct file *f)
{
printk(KERN_INFO "Driver: open()
");
return 0;
}
static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off)
{
printk(KERN_INFO "Driver: read()
");
return 0;
}
struct file_operations pugs_fops =
{
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
};
static int __init ofcd_init(void) /* Constructor */
{
printk(KERN_INFO "Namaskar: ofcd registered");
if (alloc_chrdev_region(&first, 0, 1, "Shweta") < 0)
{
return -1;
}
if ((cl = class_create(THIS_MODULE, "chardrv")) == NULL)
{
unregister_chrdev_region(first, 1);
return -1;
}
if (device_create(cl, NULL, first, NULL, "mynull") == NULL)
{
class_destroy(cl);
unregister_chrdev_region(first, 1);
return -1;
}
cdev_init(&c_dev, &pugs_fops);
if (cdev_add(&c_dev, first, 1) == -1)
{
device_destroy(cl, first);
class_destroy(cl);
unregister_chrdev_region(first, 1);
return -1;
}
return 0;
}
static void __exit ofcd_exit(void) /* Destructor */
{
cdev_del(&c_dev);
device_destroy(cl, first);
class_destroy(cl);
unregister_chrdev_region(first, 1);
printk(KERN_INFO "Alvida: ofcd unregistered");
}
module_init(ofcd_init);
module_exit(ofcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Character Driver");
Firstly we allocate major minor numbers for the device. Register for the range of device files and Linking the device file operations to the device driver functions.
Some of the term I didn't get are..
1) What does actually cdev_add() do? in terms of registering a device to the
kernel.
2) Registering a device to the kernel means?
3) How does a open(/dev/mynull, O_RONLY); called on a device file actually calls
the open function of driver which is mapped while initializing the device
by calling routine cdev_init(&c_dev, &pugs_fops); ?
See Question&Answers more detail:
os