I want to know the difference between these two functions:
int register_chrdev_region(dev_t first, unsigned int count, char *name); int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name); 03 Answers
See here for details on these two functions.
Registration is only really useful if you know in advance which major number you want to start with. With registration, you tell the kernel what device numbers you want (the start major/minor number and count) and it either gives them to you or not (depending on availability).
With allocation, you tell the kernel how many device numbers you need (the starting minor number and count) and it will find a starting major number for you, if one is available, of course.
Partially to avoid conflict with other device drivers, it's considered preferable to use the allocation function, which will dynamically allocate the device numbers for you.
From the link given above:
Some major device numbers are statically assigned to the most common devices. A list of those devices can be found in
Documentation/devices.txtwithin the kernel source tree. The chances of a static number having already been assigned for the use of your new driver are small, however, and new numbers are not being assigned. So, as a driver writer, you have a choice: you can simply pick a number that appears to be unused, or you can allocate major numbers in a dynamic manner.Picking a number may work as long as the only user of your driver is you; once your driver is more widely deployed, a randomly picked major number will lead to conflicts and trouble.
Thus, for new drivers, we strongly suggest that you use dynamic allocation to obtain your major device number, rather than choosing a number randomly from the ones that are currently free. In other words, your drivers should almost certainly be using
alloc_chrdev_regionrather thanregister_chrdev_region.The disadvantage of dynamic assignment is that you can't create the device nodes in advance, because the major number assigned to your module will vary. For normal use of the driver, this is hardly a problem, because once the number has been assigned, you can read it from
/proc/devices.
There's a related, but not technically duplicate, question here.
2To put in simple terms: You use register_chrdev_region when you have the device ID for your character driver with you and you want to inform the VFS that reserve this device ID (basically the Major Number) for your driver.
dev_t mydev; mydev = MKDEV(MAJORNO, MINORNO);//you have already decided on a static majorno and minorno register_chrdev_region(mydev, count, CHAR_DEV_NAME) //**here you are supplying the device ID in mydev** You use alloc_chrdev_region when you are asking the VFS to give you a free device ID (which is basically the major number) for your character driver.
dev_t mydev; //you are asking VFS for the device ID alloc_chrdev_region(&mydev, start_minor_no, count, CHAR_DEV_NAME) //**Here you get the device ID in mydev**. As per the LDD3 Document,
When setting up a character device is to obtain one or more device numbers to work with. The necessary function for this task is,
int register_chrdev_region(dev_t first, unsigned int count, char *name);
(or)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
Note that, register_chrdev_region works well if you know ahead of time exactly which device numbers you want. Often, however, you will not know which major numbers your device will use; there is a constant effort within the Linux kernel development community to move over to the use of dynamicly-allocated device numbers. The kernel will happily allocate a major number for you on the fly, but you must request this allocation by using a alloc_chrdev_region. Basically its a dynamic Allocation of the Major number.
Thus, for new drivers, we strongly suggest that you use dynamic allocation to obtain your major device number, rather than choosing a number randomly from the ones that are currently free. In other words, your drivers should almost certainly be using alloc_chrdev_region rather than register_chrdev_region.