Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does open works for normal file and device drivers

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()\n");
   return 0;
} 
static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off)
{
   printk(KERN_INFO "Driver: read()\n");
   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); ?
like image 816
Yogesh R.L Avatar asked Jan 24 '13 12:01

Yogesh R.L


People also ask

How does device driver works?

A driver communicates with the device through the computer bus or communications subsystem to which the hardware connects. When a calling program invokes a routine in the driver, the driver issues commands to the device (drives it).

What are the file types of device driver?

Typically, a driver is a dynamic-link library (DLL) with the . sys file name extension. Long file names are allowed, except for boot-start drivers. The software that is required to support a particular device depends on the features of the device and the bus or port to which it connects.

How do device drivers work on Linux?

Device drivers make use of standard kernel services such as memory allocation, interrupt delivery and wait queues to operate, Loadable. Most of the Linux device drivers can be loaded on demand as kernel modules when they are needed and unloaded when they are no longer being used.

Is file system a device driver?

A file system filter driver normally creates one control device object and one or more filter device objects. Because file system filter drivers are not device drivers, they do not perform direct memory access (DMA).


1 Answers

1) How does virtual file system(VFS) get to know on which file system the underline file resides?

You have to specify the file you're trying to open by its full pathname (or the current working directory).
So by traversing this directory path backwards, the first match (the deepest path) to a mount point will provide the mounted filesystem, type of filesystem and the device.

Each filesystem provides this information when it is mounted and is saved in the mount tables.
You can view this (current state) information using the mount command.

2) How does it then calls the file_open or open function of that particular filesystem to open file.

Once the filesystem is known, the ops structure for that fs is retrieved, and the open() entrypoint can be called.

1) What does actually cdev_add() do? in terms of registering a device to the kernel.

Driver registration (e.g cdev_init() for a char device) installs the driver's ops structure which lists the entrypoints of functions that the driver can perform.
cdev_add() notifies the kernel that the driver can control a specific instance of that char device type. That device instance is assigned a minor number that associates the device name in /dev to state information in the driver.
Note that device types other than char (such a network or platform (bus) devices) belong to a different subsystem, and use different registration procedures.

2) Registering a device to the kernel means?

Access to that device is now enabled.

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); ?

The driver's init() routine should only be called once when the driver is loaded. This routine should probe for the existence and operational state of all instances of the device. Resources such as interrupt lines, DMA channels and I/O port and/or memory space should be acquired. The driver registers its ops structure with kernel. The driver registers each instance of the device with kernel.

The open() call in userspace is handled by the C library. The /dev device name is translated to the device major number (which identifies which device subsystem or class, e.g tty or audio, has to process the request) and the minor number (which identifies which device driver to use and which instance of the device is accessed). The processor is switched to supervisor mode so that the kernel driver's open() routine can be called, which is retrieved from the driver's ops structure. For a bit more on the ops structure see this other answer.

like image 165
sawdust Avatar answered Sep 22 '22 10:09

sawdust