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.
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:
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.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
.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With