Related Data Structure:
Struct cdev {
Struct kobject kobj;
Struct module * owner;
Const struct file_operations * OPS;
Struct list_head list;
Dev_t dev;
Unsigned int count;
};
Struct kobj_map {
Struct probe {
Struct probe * next;
Dev_t dev;
Unsigned long range;
Struct module * owner;
Kobj_probe_t * Get;
INT (* Lock) (dev_t, void *);
Void * data;
} * Probes [255];
Struct mutex * lock;
};
Static struct char_device_struct {
Struct char_device_struct * next;
Unsigned int Major;
Unsigned int baseminor;
Int minorct;
Char name [64];
Struct file_operations * fops;
Struct cdev * cdev;/* Will die */
} * Chrdevs [chrdev_major_hash_size];
# Define chrdev_major_hash_size 255
The following article describes the character device driver in three aspects and their association:
1. Character-driven model
2. device Number of the character device
3. Access to character device files in the file system
1. Character-driven model
Each character driver is represented by a cdev structure.
In the device driver model, the kobject mapping domain is used to record the device driver.
This is represented by the struct kobj_map structure. It is embedded with an array of 255 struct probe pointers.
Kobj_map is referenced by the global variable cdev_map: static struct kobj_map * cdev_map;
Function Description:
Cdev_alloc () is used to create a cdev object.
Cdev_add () is used to add the cdev object to the driver model. It is implemented through kobj_map.
Kobj_map () creates a probe object, inserts it into an item in cdev_map, and associates probe-> data with cdev
Struct kobject * kobj_lookup (struct kobj_map * domain, dev_t Dev, int * index)
Search for the built-in kobject. (probe-> data-> kobj) of the cdev object in cdev_map Based on the device number, and return the kobject of cdev.
2. device Number of the character device
Character device master and sub-device number allocation:
The Global Array chrdevs contains 255 (value of chrdev_major_hash_size) struct char_device_struct elements.
Each corresponding primary device ID.
If a device number is assigned, a struct char_device_struct object is created and added to chrdevs.
In this way, through the chrdevs array, we can know which device numbers are allocated.
Related functions:
Register_chrdev_region () allocates the specified device number range
Alloc_chrdev_region () dynamically allocates the device range
They are mainly implemented by calling the function _ register_chrdev_region ().
Note that these two functions are only used to register the device number! To associate with cdev, call cdev_add ()
Register_chrdev () requests a specified device number and registers it to the device driver model.
What it does is:
1. register the device number by calling _ register_chrdev_region ().
2. Allocate a cdev and implement it by calling cdev_alloc ().
3. Add cdev to the driver model. In this step, the device number is associated with the driver, which is implemented by calling cdev_add ().
4. Point the cdev of the struct char_device_struct object created in step 1 to the cdev allocated in step 2. Since register_chrdev () is an old interface, this step is not required in the new interface.
3. Access to character device files in the file system
For a character device file, its inode-> I _cdev points to the character drive object cdev. If I _cdev is null, the file is not opened.
Because multiple devices can share the same driver, the I _devices IN THE inode of the character device and the list in the cdev form a linked list.
First, when the system calls open to open a character device, the chrdev_open will be executed through a series of calls.
(This article will not discuss the call process by calling. Open in def_chr_fops, and def_chr_fops.open = chrdev_open)
Int chrdev_open (struct inode * inode, struct file * filp)
What chrdev_open () Does can be summarized as follows:
1. based on the device number (inode-> I _rdev), find the corresponding driver in the character device driver model, which is achieved through kobj_lookup (), kobj_lookup () the corresponding driver cdev's kobject will be returned.
2. Set inode-> I _cdev to point to the cdev.
3. Add inode to the list of cdev-> list.
4. Use the ops of cdev to set the f_op of the file object
5. If the open method is defined in OPS, the open method is called.
6. Return.
After chrdev_open () is executed, the f_op of the file object points to the ops of cdev. Therefore, after reading and writing the device, the corresponding operations of cdev will be executed.