The
Registration process for character devices in Linux is relatively straightforward. We can usually call the Misc_register () function to register a character device. A misc device is a character device that enables the ability of a character device to be forwarded to a registered Misc device using a FoPs request. When a user invokes the interface to register a misc character device, the device minor number can be dynamically assigned, and the Class_simple_device_add () or device_create () function completes the creation of the character device when the minor number is obtained. The Misc character device registration function looks like this:
int Misc_register (struct Miscdevice * misc) {struct miscdevice;
dev_t Dev;
int err = 0;
Init_list_head (&misc->list); Mutex_lock (&MISC_MTX); Get the Misc device Semaphore List_for_each_entry (c, &misc_list, list) {//check if the device already exists if (C->minor = = Misc->min
OR) {Mutex_unlock (&MISC_MTX); Return-ebusy; If the device exists, directly returns}} if (Misc->minor = = Misc_dynamic_minor) {//dynamic assignment allocation minor number int
i = dynamic_minors; while (-i >= 0) if ((misc_minors[i>>3) & (1 << (i&7)) = = 0) brea
K
if (i<0) {mutex_unlock (&MISC_MTX);
Return-ebusy;
} Misc->minor = i; } if (Misc->minor < dynamic_minors) Misc_minors[misc->minor >> 3] |= 1 << (Misc
->minor & 7); dev = Mkdev(Misc_major, Misc->minor); Misc->this_device = Device_create (Misc_class, misc->parent, Dev, "%s", misc->name);
Create a character device (Misc device) if (Is_err (Misc->this_device)) {ERR = Ptr_err (Misc->this_device);
Goto out;
} * * ADD it to the front and so later devices can "override" * Earlier defaults * * List_add (&misc->list, &misc_list);
The device is saved to the Misc device chain, and the link list out:mutex_unlock (&MISC_MTX) is required to access the device;
return err; }
Note that the Simple_device interface Class_simple_device_add () needs to be invoked when the system device is created in the 2.6.12 kernel. In 2.6.23 you need to call the Device_create () function to complete the device registration. In the 3.2 kernel, the Simple_device interface is no longer present, so the Device_create function must be invoked, and the 3.2 kernel does not support character devices with the same minor number, which is supported in the 2.6.x kernel.
How did the system complete the FoPs function call? Answering this question requires analyzing the MISC device open process. When the misc device driver is turned on, the Misc device driver redirects the FoPs set of functions based on the minor number of the access device, which is described as follows:
static int Misc_open (struct inode * inode, struct file * file) {int minor = Iminor (Inode);
struct Miscdevice *c;
int err =-enodev;
const struct File_operations *old_fops, *new_fops = NULL;
Mutex_lock (&MISC_MTX);
List_for_each_entry (c, &misc_list, list) {///minor number to match the corresponding fops set of functions if (C->minor = minor) {
New_fops = Fops_get (c->fops);
Break
} if (!new_fops) {mutex_unlock (&MISC_MTX);
Request_module ("char-major-%d-%d", misc_major, minor);
Mutex_lock (&MISC_MTX); List_for_each_entry (c, &misc_list, list) {if (C->minor = = minor) {new_fops = FoPs
_get (C->fops);
Break
} if (!new_fops) goto fail;
Err = 0;
Old_fops = file->f_op; File->f_op = New_fops; redirectFoPs function if (file->f_op->open) {//Open device Err=file->f_op->open (inode,file);
if (err) {fops_put (FILE->F_OP);
File->f_op = Fops_get (old_fops);
} fops_put (Old_fops);
Fail:mutex_unlock (&MISC_MTX);
return err; }