It seems that each chapter has a relatively small amount of content, but learning is a step-by-step process. It is not about how much you learn in a day, but how much you can actually learn in an important day, So I advocate step by step, learn knowledge from multiple channels to complement each other.
This test code is uploaded here: char_step1. You can download and test it.
Character device registration and automatic creation of device nodes cdev the kernel uses struct cdev <Linux/cdev. h> to represent a character device struct cdev {
Struct kobject kobj; // introduction to the kobj device model later
Struct module * owner;
Const struct file_operations * OPS; // File Operations
Struct list_head list;
Dev_t dev; // device number
Unsigned int count; // number of devices
}; Register the character device for dynamic initialization: struct cdev * my_cdev = cdev_alloc ();
My_cdev-> Ops = & my_ops; static initialization: struct cdev my_cdev;
Cdev_init (& my_dev, & my_ops); register with the kernel (add device): int cdev_add (struct cdev * Dev, dev_t num, unsigned count );
Dev: point to the device structure with the characters initialized
Num: Device number
Count: number of devices to be added
Return Value:
0 is returned successfully. An error code is returned. The device may be called immediately when it is registered. Therefore, do not call cdev_add before the driver is ready to process device operations.
Deregister character device:
You need to cancel the void cdev_del (struct cdev *) of the device when you do not need to use the West device *);
Early Methods
A simple and easy-to-use method is available for registering character devices before the 2.6 kernel, but it is not recommended because this method will disappear from the kernel at the end.
Register a character device: static inline int register_chrdev (unsigned int major,
Const char * Name, const struct file_operations * FoPs );
Major: master device number (when major is set to 0, a kernel allocates an available master device number and returns it)
Name: Driver name
FoPs: File Operations
Disadvantage: you cannot register multiple devices at the same time. It creates a cdev structure by default. In this case, it cannot use a primary/secondary device number greater than 255.
Device deregistering: static inline void unregister_chrdev (unsigned int major, const char * name)
Automatic Creation of device nodes
In the previous program, although a device number can be obtained, a device node is not generated in the/dev/directory.
Create mknod/dev/device_name C major minor manually
Device_name: Device Name,
C: create a character device node (similarly, B Indicates creating a block Device File node)
Major: master device number
Minor: Sub-device number
This can be understood during testing, but when a module is to be released, it is too inconvenient. ① check whether the device is successfully created first, ② view the master device number of the registered device, ③ enter the command to create a file Node
Of course, you can write a shell script to complete these tasks.
Automatically create a device Node
The required slimming kernel space supports udev. During Kernel configuration and busybox configuration, you must specify
The structure of struct class and struct Devic is defined in the kernel <Linux/device. h>
Create a class structure # define class_create (owner, name )\
({\
Static struct lock_class_key _ key ;\
_ Class_create (owner, name, & __ key );\
})
Owner indicates the pointer to this module.
Name indicates the device name.
After calling this function, create a struct class structure under sysfs, and then call struct device * device_create (struct class * CLs,
Struct device * parent,
Dev_t devt, void * drvdata,
Const char * FMT ,...)
Create a device node in the/dev directory
CLS: the struct class structure pointer created by the above function
Parent: pointing to the device's parent node device (if null is not specified
Devt: Device Number of the added Device
Drvdata: callback function parameters
FMT, argS: one or more device names
Now we have created a device node.
Delete A device Node
When the device is not needed, we need to delete the device node: void device_destroy (struct class *Class, Dev_t devt); // delete a device Node
Void class_destroy (struct class * CLs); // Delete the struct class structure under sysfs
Some in-depth implementation mechanisms have not been carefully studied. If you are interested, please refer to the relevant materials.
Instance: Initialize and add devices to the kernel
- Simple_cdev = cdev_alloc (); // dynamically initializes character Devices
- If (simple_cdev! = NULL)
- {
- Simple_cdev-> Ops = & simple_fops; // File Operations
- Simple_cdev-> owner = this_module;
- }
- Else
- {
- Printk (kern_err "alloc cdev err no memory ");
- Unregister_chrdev_region (Dev, dev_count); // release the device number if an error occurs in resource allocation.
- Return-enomem;
- }
- Err = cdev_add (simple_cdev, Dev, dev_count); // Add a device to the kernel
- If (ERR <0)
- {
- Printk (kern_err "add cdev err \ n ");
- Goto error1;
- }
- Else
- {
- # If simple_debug
- Printk (kern_info "add char Dev OK! \ N ");
- # Endif
- }
Automatically create a device Node
- Simple_class = class_create (this_module, simple_name );
- If (simple_class = NULL)
- {
- Printk (kern_err "create simple class error \ n ");
- Goto error2;
- }
- Else
- {
- # If simple_debug
- Printk (kern_info "create simple class OK! \ N ");
- # Endif
- }
- Simple_dev = device_create (simple_class, null, Dev, null, simple_name );
- If (simple_dev = NULL)
- {
- Printk (kern_err "create device error ");
- Goto error3;
- }
- Else
- {
- # If simple_debug
- Printk (kern_info "create simple device OK! \ N ");
- # Endif
- }
Delete A device node and deregister a character device
- Dev = mkdev (simple_major, simple_minor); // calculate the device number.
- Device_destroy (simple_class, Dev); // delete a device Node
- Class_destroy (simple_class); // Delete and release the class structure
- Cdev_del (simple_cdev); // cancel the device