major number minor number and driver loading
device, driver, linux, linux-kernel
Solution
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:
- You plug in some block/char device to some bus.
- 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.
- 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.
- 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.
- 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 `printk`s 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`.
Problem
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.