The first is the use of Mknod manual Create: # mknod <devfilename> <devtype> <major> <minor>
the second is self - Create device node: using udev (Mdev) to automate the creation of device files, first of all ensure that Udev (Mdev) is supported and configured by BusyBox.
Specific UDEV related knowledge is not elaborated here, you can shift the Linux file system and equipment file system--udev device file system, here is mainly about the use of methods.
The main thing to do with support for Udev in driving is to call Class_create (...) in the code that drives the initialization. Create a class for the device, and then call Device_create (...) for each device. Create the corresponding device .
The struct class structure defined in the kernel, as the name implies, a struct class struct type variable corresponding to a class, the kernel also provides class_create (...) function, which can be used to create a class, this class is stored under Sysfs , once the class is created, then the Device_create (...) is called. function to create the appropriate device node in the/dev directory.
In this way, when the module is loaded, udev in the user space automatically responds to the Device_create () function,/sysfs to find the corresponding class to create the device node.
The following is a parse of two functions:
Support for automatic character device file generation
Linux/device.h
struct class *class_create (structconstChar *name); /* function: Create a directory under the/sys/class directory, the directory name is the parameter specified by name: struct module *owner-this_module const char *name-device name return value: Success : Class pointer failed:-BOOL Is_err (const void *PTR) to determine if error long ptr_err (const void *PTR) Conversion error code * /
void Class_destroy (struct class *cls); /* function: Remove the directory parameter that the class pointer points to: struct class *cls-class pointer */
struct device *device_create (struct class *cls, struct device *parent, dev_t DEVT, void *drvdata, const char *fmt, ...); /* function: Create a directory under the directory that the class pointer points to, directory name by const char *FMT, ... Point and Export device information (dev_t) Parameters: struct class *cls-class pointer struct device *parent-parent object, NULL dev_t devt-device number void *drv Data-drive Private Data const char *FMT, ...-FMT is a directory name string format, ... is the indeterminate parameter return value: Success-Device pointer failure-BOOL Is_err (const void *PTR) to determine if error long Ptr_err (const void *PTR) Conversion error code */
void Device_destroy (structclass *cls, dev_t devt); /* function: Delete device_create created directory parameter: struct class *cls-class pointer dev_t devt-device number */
Create order
struct class *class_create (struct module *owner, const char *name);
struct Device *device_create (struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
Delete Order
void Device_destroy (struct class *cls, dev_t devt);
void Class_destroy (struct class *cls);
Instance:
#include <linux/init.h>#include<linux/module.h>#include<linux/kernel.h>#include<linux/cdev.h>#include<linux/fs.h>#include<linux/errno.h>#include<asm/current.h>#include<linux/sched.h>#include<linux/device.h>Module_license ("GPL");Static struct class*cls =NULL;Static intMajor =0;Static intMinor =0;Const intCount =6;#defineDevname "Demo"Static structCdev *demop =NULL;//turn on the deviceStatic intDemo_open (structInode *inode,structFile *Filp) { //get command and PIDPRINTK (Kern_info"%s:%s:%d\n",__file__, __func__, __line__);return 0;}//turn off the deviceStatic intDemo_release (structInode *inode,structFile *Filp) { //get major and minor from InodePRINTK (Kern_info"%s:%s:%d\n", __file__, __func__, __line__); return 0;}Static structFile_operations FoPs ={. Owner=this_module,. Open=Demo_open,. Release=Demo_release,};Static int__init Demo_init (void) {dev_t devnum; intret, I; structDevice *DEVP =NULL; //1. Alloc Cdev objDemop =Cdev_alloc (); if(NULL = =demop) { return-Enomem; } //2. Init cdev objCdev_init (DEMOP, &fops); RET= Alloc_chrdev_region (&Devnum, Minor, Count, Devname); if(ret) {GotoErr_step; } Major=MAJOR (Devnum); //3. Register Cdev objRET =Cdev_add (Demop, Devnum, Count); if(ret) {GotoErr_step1; } CLS=class_create (This_module, devname); if(Is_err (CLS)) {ret=Ptr_err (CLS); GotoErr_step1; } for(i = minor; i < (Count+minor); i++) {DEVP= Device_create (CLS, NULL, MKDEV (major, I), NULL,"%s%d", Devname, i); if(Is_err (DEVP)) {ret=Ptr_err (DEVP); GotoErr_step2; } } return 0; ERR_STEP2: for(i; I >= minor; i--) {Device_destroy (CLS, MKDEV (Major, I)); } Class_destroy (CLS); Err_step1:unregister_chrdev_region (Devnum, Count); Err_step:cdev_del (DEMOP); //get command and PIDPRINTK (Kern_info"%s:%s:%d-fail.\n", __file__, __func__, __line__); returnret;}Static void__exit Demo_exit (void){ inti; //get command and PIDPRINTK (Kern_info"%s:%s:%d-leave.\n", __file__, __func__, __line__); for(I=minor; i < (Count+minor); i++) {Device_destroy (CLS, MKDEV (Major, I)); } Class_destroy (CLS); Unregister_chrdev_region (MKDEV (major, minor), count); Cdev_del (DEMOP);} Module_init (Demo_init); Module_exit (demo_exit);
Below you can see the correspondence between several classes of class names:
Automatic generation of Linux device files