Http://blog.csdn.net/iczyh/archive/2008/11/25/3373350.aspx
Each character device in the kernel corresponds to a variable in the cdev structure. Its definition is as follows:
Struct cdev {
Struct kobject kobj; // each cdev is a kobject
Struct module * owner; // point to the module implementing the driver
Const struct file_operations * OPS; // Method for manipulating the device file of this character
Struct list_head list; // inode-> I _devices linked list header of the device file corresponding to the cdev character
Dev_t dev; // start device ID
Unsigned int count; // device range number size
};
A cdev generally has two initialization Methods: static and dynamic.
Static Memory definition initialization:
Struct cdev my_cdev;
Cdev_init (& my_cdev, & FOPS );
My_cdev.owner = this_module;
Dynamic Memory definition initialization:
Struct cdev * my_cdev = cdev_alloc ();
My_cdev-> Ops = & FOPS;
My_cdev-> owner = this_module;
The functions of the two methods are the same, but the memory zone used is different, depending on the actual data structure requirements.
The following two functionsCodeTo see the differences between them.
Struct cdev * cdev_alloc (void)
{
Struct cdev * P = kzarloc (sizeof (struct cdev), gfp_kernel );
If (p ){
Init_list_head (& P-> list );
Kobject_init (& P-> kobj, & ktype_cdev_dynamic );
}
Return P;
}
Void cdev_init (struct cdev * cdev, const struct file_operations * FoPs)
{
Memset (cdev, 0, sizeof * cdev );
Init_list_head (& cdev-> list );
Kobject_init (& cdev-> kobj, & ktype_cdev_default );
Cdev-> Ops = fops;
}
It can be seen that the functions of both functions are basically the same, but cdev_init () has assigned a cdev-> OPS value.
After cdev is initialized, you need to add it to the system. Therefore, you can call the cdev_add () function. The pointer to the cdev structure, the start device number, and the device number range.
Int cdev_add (struct cdev * P, dev_t Dev, unsigned count)
{
P-> Dev = dev;
P-> COUNT = count;
Return kobj_map (cdev_map, Dev, Count, null, exact_match, exact_lock, P );
}
The kobj_map () function will not be expanded. I just want to give a general introduction to its principles. All character devices in the kernel are recorded in a cdev_map variable in the kobj_map structure. The variable in this structure contains a hash to quickly access all objects. The kobj_map () function is used to save the character device number and the cdev structure variable to the cdev_map hash list. When you want to open a character device file in the future, call the kobj_lookup () function to find the cdev Structure Variable Based on the device number and retrieve the ops field.
when the driver of a character device no longer needs it (such as uninstalling the module), you can use the cdev_del () function to release the memory occupied by cdev.
void cdev_del (struct cdev * P)
{< br> cdev_unmap (p-> Dev, p-> count );
kobject_put (& P-> kobj);
}< br> cdev_unmap () calls kobj_unmap () to release objects in the cdev_map hash list. Kobject_put () releases the cdev structure itself.