Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

major number minor number and driver loading

I'm a beginner. I've some idea about major number and minor number related with device driver. Also I know that most of the devices that can be plugged into a Linux system have a major number. And based on this major number, the corresponding driver is loaded. I've this doubt, Please tell me how the kernel reads the major number from the device when it is plugged in? Please explain the steps from device plugin till the driver loading, as simple as possible.

Thanks in advance.

like image 492
Ajish Alfred Avatar asked Jun 22 '12 19:06

Ajish Alfred


2 Answers

Major/minor numbers are for block and character devices.

You don't detect a major number from a device. Maybe you think USB devices can communicate device numbers and Linux uses those, but the USB vendor/product IDs aren't related to major numbers. What if you plug a totally dumb serial device into a serial port? The kernel has no way to know that you plugged/unplugged something.

So, if for example you want a major number for your character device, either you use

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

like NKamrath said, or you use an absolute one. Beware, however, that many are reserved.

As far as I know, here are the steps you're asking for:

  1. You plug in some block/char device to some bus.
  2. Depending on the bus (USB, PCI, PCI Express, SCSI, I²C, etc.), the bus (probably) sends an interrupt signal that will one day or another get to the CPU and thus to Linux.
  3. The interrupt routine does the necessary job, knowing the bus type and its internal mechanism, to load the appropriate driver for this device (if it exists, and for sure it does) and execute its initialization function.
  4. The device driver's initialization function registers (e.g. register_chrdev_region) a major number if it has one reserved (see this famous reserved list); otherwise it asks the kernel to allocate one for it (e.g. alloc_chrdev_region); the driver will also reserve a minor region for this driver.
  5. The driver sets a few callbacks (open/close/read/write) and asks the kernel to associate them with the device number.

At this point, you can communicate with the driver using its device number, but how? There's nothing in /dev yet... One way of doing it is using mknod when you know the major/minor pair for what you want to communicate with. You would issue:

# mknod /dev/mydevice c 232 4

... which is: please make a device node at /dev/mydevice which is linked to character (c) device with major 232 and minor 4. But how do you know those numbers, then? They might be absolute (reserved list) or maybe the driver printks it so you can do it manually.

But here's something better.

Still in the device driver's initialization function: the driver registers the device as a Sysfs device (see device_create). This will put the device into the /sys tree and its node (a directory) will have a file called uevent. If you cat it, it will output something like

MAJOR=232
MINOR=4
DEVNAME=whatever

Try it:

$ cat /sys/class/tty/console/uevent

Does it match

$ ls -l /dev/console

?

Now, udev is the user space program responsible for the management of /dev. Overall, it simply scans the /sys tree in order to populate /dev automatically. You may also see all character and block devices major/minor like this:

$ ls /sys/dev/char
$ ls /sys/dev/block

That's about it. If you want to understand all this better, develop a dummy driver and try making it appear automatically into /dev.

like image 173
eepp Avatar answered Sep 28 '22 10:09

eepp


If you know the major number in advance, you can use

int register_chrdev_region(dev_t first, unsigned int count);

To allow the kernel to dynamically assign the device a major number use

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, 
                    char *name);

To read the major number use

int MAJOR(dev_t dev);

To insert a device or driver you must use the insmod commmand. The kernel then attempts to use the number you gave it or dynamically assigns it a free major number if you used the alloc function. Properly explaining the inner workings of the kernel and driver design would take a lot of explaining. However, there is a great free book which is an easy read (for a code book) called Linux Device Drivers 3rd Edition that will give you a very good introduction to drivers and even if you only read the first 3 chapters (roughly 100 pages) you will get a good understanding for what I think you are asking. Also, all the source code for the examples is available so you can hack their demos and get started writing drivers faster!

like image 44
NKamrath Avatar answered Sep 28 '22 10:09

NKamrath