Yogesh R.L
Yogesh R.L

Reputation: 619

The role of major and minor numbers in device driver

I am learning Linux device driver and got stuck on the major, minor numbers. What I have so far is:

Some of the Questions are yet troubling me...

  1. Does the fops structure is linked to the f_ops field of file structure of the device file when we initialize device like cdev_init(&c_dev, &fops);?
  2. How does a call to open("/dev/mydev", O_RONLY); actually calls the open() function of the drivers. Does numbers comes in picture here to find the actual write method of device driver, if yes how?
  3. The numbers, major is used to identify device driver and minor to device file. What is the actual role of the the this numbers when we perform operations on the device file like open() read() write() etc.?

Upvotes: 8

Views: 6417

Answers (1)

solofox
solofox

Reputation: 251

I think the story should starts from what happened when you type:

mknod /dev/c83 c 8 3

it will call ext2_mknod("/dev", "c83", CHAR, DEV(8, 3)), most file systems implement mknod as a wrapper of init_special_inode:

void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
        inode->i_mode = mode;
        if (S_ISCHR(mode)) {
                inode->i_fop = &def_chr_fops;
                inode->i_rdev = rdev;
        } else if (S_ISBLK(mode)) {
                inode->i_fop = &def_blk_fops;
                inode->i_rdev = rdev;
        } else if (S_ISFIFO(mode))
                inode->i_fop = &def_fifo_fops;
        else if (S_ISSOCK(mode))
                inode->i_fop = &bad_sock_fops;
        else
                printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n",
                       mode);
}

when you finally call open("/dev/c83"), it will goes into function def_chr_fops.chrdev_open, which will replace the fops for file "/dev/c83" with the fops your registered in cdev_init():

int chrdev_open(struct inode * inode, struct file * filp)
{
    struct cdev *p;
    ...
    p = inode->i_cdev;
    ...
    filp->f_op = fops_get(p->ops);
    ...
    if (filp->f_op->open) {
        lock_kernel();
        ret = filp->f_op->open(inode,filp);
        unlock_kernel();
    }
    ...
    return ret;
 }

after that, every system call such as read/write/close goes directly to functions pointers registered in cdev_init()!

so, for your first question:

  1. yes, as you see in chrdev_open().
  2. yes, since the fops of devices is really same as the one registered in cdev_init
  3. plays a importance role in open(), since open() use pairs to find the correct device drivers. but after that, other file operations, such as read/write/close(), don't take part in again, everything goes through function pointers in fops resolved in open().

Upvotes: 11

Related Questions