views:

178

answers:

2

Hi ,

I am trying to understand how device driver works in linux.

  1. I have a device node as follows (Major number 89, device name i2c-0)

     crw-r--r--    1 0        0         89,   0 Sep 29 01:36 /dev/i2c-0
    
  2. I have the i2c driver with the name i2c.ko and I will do insmod i2c.ko during start up.

  3. And in the driver , following function will be called during initialization:

    register_chrdev(89, "i2c", &i2chtv_fops)<0    // not "i2c-0"
    

My question is : When user call open("/dev/i2c-0", O_RDWR),how the kernel knows which driver to use ? I noticed the device name is i2c-0 but registered device name is i2c. Is it because they are use the same major number that the kernel can use the correct driver?

+2  A: 

Yes, major numbers select the driver and minor numbers select "units" (whatever that may be; for the console driver, it's the different screens).

The -0 you see is the "unit" (in case you have more than a single i2c bus in your system).

Aaron Digulla
We have two i2c bus in our system. And used two different major number for them. Is this not the stardard way to do it? What is the use of registered device name (name in register_chrdev call)?
pierr
That depends. If you use minor numbers, you have to manage the units in your code. If you use two major numbers, then the kernel will allocate two different device structures for you. So the latter will make it more simple, the former will allow you squeeze a more few bytes of free RAM out of the system (if your "unit" handling code is small enough).
Aaron Digulla
+2  A: 

The major number tells you which driver handles which device file. The minor number is used only by the driver itself to differentiate which device it's operating on, just in case the driver handles more than one device.

Adding a driver to your system means registering it with the kernel. This is synonymous with assigning it a major number during the module's initialization. You do this by using the register_chrdev function, defined by linux/fs.h.

 int register_chrdev(unsigned int major, const char *name,
       struct file_operations *fops);

where unsigned int major is the major number you want to request, const char *name is the name of the device as it'll appear in /proc/devices and struct file_operations *fops is a pointer to the file_operations table for your driver. A negative return value means the registertration failed. Note that we didn't pass the minor number to register_chrdev. That's because the kernel doesn't care about the minor number; only our driver uses it.

From here

pierr