When writing a Linux Device Driver, you often use the mknod command to manually create a device node (including many examples in ldd3). In fact, the Linux Kernel provides us with a set of functions, it can be used to automatically create a device node in the/dev directory when the module is loaded, and delete the node when the module is detached.
The struct class struct is defined in the kernel. As the name suggests, a struct class struct type variable corresponds to a class, and the kernel also provides class_create (...) Function, you can use it to create a class, which is stored under sysfs. Once this class is created, call device_create (...) Function to create a device node in the/dev directory. In this way, when the module is loaded, udev in the user space will automatically respond to device_create (...) Function to find the corresponding class under/sysfs to create a device node.
In addition, the device_create_file function can be used to create an attribute file under/sys/class/to perform specific data operations by reading and writing the file.
- 1
I. class_create
- 2
Ii. device_create
- 3
3. device_create_file
- 3.1
A. Use device_create_file in the driver to create an attribute File
- 3.2
B. Read attributes in user space
- 4
Iv. Example
|
I. class_create
Official notes:
/* This is a #define to keep the compiler from merging different * instances of the __key variable */#define class_create(owner, name)\({\static struct lock_class_key __key;\__class_create(owner, name, &__key);\})/** * class_create - create a struct class structure * @owner: pointer to the module that is to "own" this struct class * @name: pointer to a string for the name of this class. * @key: the lock_class_key for this class; used by mutex lock debugging * * This is used to create a struct class pointer that can then be used * in calls to device_create(). * * Returns &struct class pointer on success, or ERR_PTR() on error. * * Note, the pointer created here is to be destroyed when finished by * making a call to class_destroy(). */struct class *__class_create(struct module *owner, const char *name, struct lock_class_key *key)
The key sentence is:
* This is used to create a struct class pointer that can then be used * In callto device_create (). --> This function is used to create a struct pointer of a struct class. This pointer can be used as a parameter of the device_create () function.
That is to say, this function is used before calling device_create () to create a variable of the struct class type and return its pointer.
Ii. device_create
Official notes:
/** * device_create - creates a device and registers it with sysfs * @class: pointer to the struct class that this device should be registered to * @parent: pointer to the parent struct device of this new device, if any * @devt: the dev_t for the char device to be added * @drvdata: the data to be added to the device for callbacks * @fmt: string for the device's name * * This function can be used by char device classes. A struct device * will be created in sysfs, registered to the specified class. * * A "dev" file will be created, showing the dev_t for the device, if * the dev_t is not 0,0. * If a pointer to a parent struct device is passed in, the newly created * struct device will be a child of that device in sysfs. * The pointer to the struct device will be returned from the call. * Any further sysfs files that might be required can be created using this * pointer. * * Returns &struct device pointer on success, or ERR_PTR() on error. * * Note: the struct class passed to this function must have previously * been created with a call to class_create(). */struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...)
First, explain "sysfs": sysfs is a virtual file system provided by linux2.6. In the device model, sysfs file system is used to represent the structure of the device, reflects the layered image of the device to the user space, so that you can modify the property value of the device by modifying the File Attribute in sysfs; sysfs is mounted to the "/sys" folder under the root directory.
3. device_create_file
Official notes:
/** * device_create_file - create sysfs attribute file for device. * @dev: device. * @attr: device attribute descriptor. */int device_create_file(struct device *dev, const struct device_attribute *attr)
When using this function, you must reference the device * pointer returned by device_create to create an attribute file under/sys/class, this allows you to complete data operations by reading and writing this property file.
For example:
A. Use device_create_file in the driver to create an attribute File
Static device_attr (Val, s_irugo | s_iwusr, hello_val_show, hello_val_store);/* read the Val value of the Register to the buffer Buf, use */static ssize_t _ hello_get_val internally (struct xxx_dev * Dev, char * BUF) {int val = 0; /* synchronous access */If (down_interruptible (& (Dev-> SEM) {return-erestartsys;} val = Dev-> val; up (& (Dev-> SEM); Return snprintf (BUF, page_size, "% d/N", Val );} /* write the buffer Buf value to the device register Val and use */static ssize_t _ hello_set_val (struct xxx_dev * Dev, const char * Buf, size_t count) internally) {int val = 0;/* convert the string to a number */val = simple_strtol (BUF, null, 10 ); /* synchronous access */If (down_interruptible (& (Dev-> SEM) {return-erestartsys;} Dev-> val = val; up (& (Dev-> SEM); Return count;}/* read the device attribute Val */static ssize_t hello_val_show (struct device * Dev, struct device_attribute * ATTR, char * BUF) {struct xxx_dev * hdev = (struct xxx_dev *) dev_get_drvdata (Dev); Return _ hello_get_val (hdev, Buf );} /* write the device attribute Val */static ssize_t hello_val_store (struct device * Dev, struct device_attribute * ATTR, const char * Buf, size_t count) {struct xxx_dev * hdev = (struct xxx_dev *) dev_get_drvdata (Dev); Return _ hello_set_val (hdev, Buf, count );} /* module Loading Method */static int _ init xxx_init (void ){... /* Create the attribute file Val */err = device_create_file (temp, & dev_attr_val) in the/sys/class/XXX/xxx directory; If (ERR <0) {printk (kern_alert "failed to create Attribute Val. "); goto destroy_device ;}...}
B. Read attributes in user space
...read(dev->fd, val, sizeof(*val));...write(dev->fd, &val, sizeof(val));...
Iv. Example
/* Create the device category directory xxx */g_vircdev_class = class_create (this_module, vircdev_class_name) under the/sys/class/directory; If (is_err (g_vircdev_class )) {err = ptr_err (g_vircdev_class); printk (kern_alert "failed to create class. \ n "); goto class_create_err;}/* Create the device file xxx */Dev = device_create (g_vircdev_class, null, respectively in the/dev/directory and/sys/class/xxx directory, devt, null, vircdev_device_name); If (is_err (Dev) {err = ptr_err (Dev); printk (kern_alert "failed to create device. \ n "); goto device_create_err;}/* Create the attribute file Val */err = device_create_file (Dev, ATTR) in the/sys/class/XXX/xxx directory ); if (ERR <0) {printk (kern_alert "failed to create Attribute file. "); goto device_create_file_err ;}