Register_chrdev_region () and alloc_chrdev_region ()

Source: Internet
Author: User

Reproduced http://blog.sina.com.cn/s/blog_620b71230100f71g.html

Character device register_chrdev_region (), alloc_chrdev_region
 

All assigned character device numbers in the kernel are recorded in a chrdevs hash. Each element in the hash is a char_device_struct structure, which is defined as follows:

Static struct char_device_struct {
Struct char_device_struct * next;// Pointer to the next element in the hashed list
Unsigned int Major;// Master device number
Unsigned int baseminor;// Start device number
Int minorct;// The range of device numbers
Char name [64];// Process the name of the device driver within the device serial number range
Struct file_operations * fops;// Not used
Struct cdev * cdev;// Pointer to the driver descriptor of the character device
} * Chrdevs [chrdev_major_hash_size];

Note that the kernel does not define a char_device_struct structure for each character device number, but a char_device_struct structure for the range of device numbers corresponding to the same character device driver. The size of the chrdevs hash is 255. The hash algorithm inserts the master device number in the device serial number range of each group of characters in the 255 modulo mode into the corresponding hash bucket. The range of character device numbers in the same hash bucket is sequentially sorted by the start device number.

Register
The kernel provides three functions to register a set of character device numbers: register_chrdev_region (), alloc_chrdev_region (), and register_chrdev (). All three functions call a common _ register_chrdev_region () function to register a set of device serial numbers (that is, a char_device_struct structure ).

Register_chrdev_region (dev_t first, unsigned int count, char * name)
First: the initial value of the range of device numbers to be allocated (the number of devices is always 0 );
Count: continuous number range.
Name: ID of the associated device. (/proc/devices );
Dynamic Allocation:
Int alloc_chrdev_region (dev_t * Dev, unsigned int firstminor, unsigned int count, char * Name );
Firstminor: usually 0;
* Dev: stores the returned device number;
Release:
Void unregist_chrdev_region (dev_t first, unsigned int count );
Call documentation/devices.txt to find the assigned device number.

So let's take a look at the implementation code of the _ register_chrdev_region () function.

Static struct char_device_struct * _ register_chrdev_region (unsigned int major, unsigned int baseminor, int minorct, const char * name)
{
Struct char_device_struct * CD, ** CP;
Int ret = 0;
Int I;

Cd = kzarloc (sizeof (struct char_device_struct), gfp_kernel );
If (Cd = NULL)
Return err_ptr (-enomem );

Mutex_lock (& chrdevs_lock );

If (Major = 0 ){
For (I = array_size (chrdevs)-1; I> 0; I --)
If (chrdevs [I] = NULL)
Break;

If (I = 0 ){
Ret =-ebusy;
Goto out;
}
Major = I;
Ret = major;
}

CD-> major = major;
CD-> baseminor = baseminor;
CD-> minorct = minorct;
Strncpy (CD-> name, name, 64 );

I = major_to_index (Major );

For (Cp = & chrdevs [I]; * CP; CP = & (* CP)-> next)
If (* CP)-> major |
(* CP)-> major = major & (* CP)-> baseminor> = baseminor) | (* CP) -> baseminor + (* CP)-> minorct> baseminor ))))
Break;


If (* CP & (* CP)-> major = major ){
Int old_min = (* CP)-> baseminor;
Int old_max = (* CP)-> baseminor + (* CP)-> minorct-1;
Int new_min = baseminor;
Int new_max = baseminor + minorct-1;


If (new_max> = old_min & new_max <= old_max ){
Ret =-ebusy;
Goto out;
}


If (new_min <= old_max & new_min> = old_min ){
Ret =-ebusy;
Goto out;
}
}

CD-> next = * CP;
* CP = Cd;
Mutex_unlock (& chrdevs_lock );
Return CD;
Out:
Mutex_unlock (& chrdevs_lock );
Kfree (CD );
Return err_ptr (RET );
}
Function _ register_chrdev_region () mainly performs the following steps:
1. assign a new char_device_struct structure and fill it with 0.
2. If the primary device number range of the requested device number is 0, the device driver requests a dynamic allocation of a primary device number. The principle of dynamically allocating the master device number is to look forward from the last bucket in the hash list. The bucket is empty and the master device number is the serial number of the corresponding hash bucket. Therefore, the dynamically assigned master device number is always less than 256. If each bucket has a character device number, the dynamic allocation will fail.
3. Set the initial device number, range, and driver name in the char_device_struct structure according to the parameters.
4. Calculate the hash bucket corresponding to the master device number and find the correct location for the new char_device_struct structure. In addition, if the device number range is repeated, an error is returned.
5. Insert the new char_device_struct structure into the hash and return the address of the char_device_struct structure.

After analyzing _ register_chrdev_region (), let's look at the three registration functions one by one. First, register_chrdev_region ().

The register_chrdev_region () function is used to allocate a specified range of device numbers. If the range of the requested device number spans the number of the master device, the device number in the allocation range is divided into smaller sub-ranges by the number of the master device, call _ register_chrdev_region () on each subfield (). If one of them fails to be allocated, all previously successfully allocated items will be returned.

The alloc_chrdev_region () function is used to dynamically apply for the range of device numbers. This function does not seem to check the range is too large, but dynamic allocation always finds an empty hash bucket, so the problem is not serious. Return the actual start device number through the pointer parameter.

The last register_chrdev () is a function that allocates the range of device numbers in old-fashioned ways. It allocates a separate master device number and 0 ~ The range of sub-device numbers of 255. If the applied primary device number is 0, one is dynamically allocated. The function also needs to input a pointer to the file_operations structure, and a new cdev structure is automatically assigned to the function. For more information, see the registration of character device drivers.

Cancel
Similar to the range of device numbers for registration and allocation characters, the kernel provides two functions for unregister_chrdev_region () and unregister_chrdev () for unregister_chrdev (). They all call the _ unregister_chrdev_region () function.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.