Linux kernel macro DEVICE_ATTR use

1 Introduction

In writing Linux drivers, use DEVICE_ATTR macro, you can define a struct device_attribute device properties, and use sysfs API functions, you can create a properties file in the device directory, when we realized the show and store function in the driver , you can use cat and echo commands to the device properties to read and write files created out of, so as to achieve the control function of the device.

 

2, the definition of the macro DEVICE_ATTR

Before explaining DEVICE_ATTR macro, to understand the basic structure, the first structure is a struct attribute, which is defined in the include / linux / device.h, the structure is defined as follows:

struct attribute {
    const char        *name;
    umode_t            mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    bool            ignore_lockdep:1;
    struct lock_class_key    *key;
    struct lock_class_key    skey;
#endif
};

This structure has two important members, namely name and mode, in which name represents the name of the property, generally expressed as a file name, mode read and write permissions on behalf of the property, that is, read and write permissions attributes of the file.

Detailed permissions on the file, you can refer to the following links:

https://blog.csdn.net/DLUTBruceZhang/article/details/8658475

The next is to understand the structure struct device_attribute, /linux/device.h defined in the structure include, defined as follows:

/* interface for exporting device attributes */
struct device_attribute {
    struct attribute    attr;
    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
            char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count);
};

This fact is further encapsulated structure struct attribute structure, and provides two function pointer, the function Show attribute file for reading the device, and is used to store attribute file writing device, when we drive the Linux after the program is implemented in these two functions, you can use cat and echo commands to the device properties file read and write operations.

Understand what the basic structure, then further analyzed to achieve macro DEVICE_ATTR in the Linux kernel source code, the macro DEVICE_ATTR defined in include / linux / device.h file as follows:

#define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

Macros defined in the __ATTR include / linux / sysfs.h file as follows:

#define __ATTR(_name, _mode, _show, _store) {                \
    .attr = {.name = __stringify(_name),                \
         .mode = VERIFY_OCTAL_PERMISSIONS(_mode) },        \
    .show    = _show,                        \
    .store    = _store,                        \
}

Can be found on macro expansion, in fact, achieve the function macro DEVICE_ATTR is the definition of a struct device_attribute structure variable dev_attr_name, the members of the inside initialized, including struct attribute name inside the structure and mode member variable, and then there are achieved properties file read and write show and store function assignment is very simple.

 

3, an example of use

Next, an example using macro DEVICE_ATTR analyzed, the sample to a virtual device in the cores 100 bytes, read and write functions in the device driver file attributes, for example:

First, define the attributes of the device, and the device attribute file read and write functions implemented:

static ssize_t mydevice_show(struct device *dev, struct device_attribute *attr,
        char *buf)
{
    return sprintf(buf, "%s\n", mybuf);
}
static ssize_t mydevice_store(struct device *dev, struct device_attribute *attr,
         const char *buf, size_t count)
{
    sprintf(mybuf, "%s", buf);

    return count;
}
static DEVICE_ATTR(mydevice, 0644, mydevice_show, mydevice_store);

In the above code, use the macro DEVICE_ATTR defines a mydevice properties file, and read and write permissions to the attributes of the file: the file owner can read and write, group and others can only read code also implements the properties file read and write functions mydevice_show () and mydevice_store (), when a cat and echo commands in user space, will be called to achieve two functions.

The next module is a function of loading, when the loading module will be called, the function code is implemented as follows:

int __init mydevice_init(void)
{
    int ret;
    struct device *mydevice;
    
    major = register_chrdev(0, "mydevice", &myfops);
    if (major < 0) {
        ret = major;
        return ret;
    }
    
    myclass = class_create(THIS_MODULE, "myclass");
    if (IS_ERR(myclass)) {
        ret = -EBUSY;
        goto fail;
    }
    
    mydevice = device_create(myclass, NULL, MKDEV(major, 0), NULL, "mydevice");
    if (IS_ERR(mydevice)) {
        class_destroy(myclass);
        ret = -EBUSY;
        goto fail;
    }

    ret = sysfs_create_file(&mydevice->kobj, &dev_attr_mydevice.attr);
    if (ret < 0)
        return ret;

    return 0;

fail:
    unregister_chrdev(major, "mydevice");
    returnright; 
}

Function first calls register_chrdev () to complete the dynamic application for a major number, the name of the device is mydevice, then call class_create () and device_create () to dynamically create a class myclass and mydevice equipment device belongs in sysfs, should be noted that, these two function calls to return the results of error detection, and finally, use sysfs API function sysfs_create_file () to create an attribute file in sysfs device, complete the initialization module.

The next function of the module is unloaded, the code function as follows:

void __exit mydevice_exit(void)
{
    device_destroy(myclass, MKDEV(major, 0));
    class_destroy(myclass);
    unregister_chrdev(major, "mydevice");
}

Module unloading and loading function function module is the opposite operation, you need to call device_destory () and class_destory () to load the module myclass and mydevice created for destruction, then call unregister_chrdev () dynamically allocates major number to be released.

Full driver code is as follows:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/sysfs.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/fs.h>

static char mybuf[100] = "mydevice";
static int major;
static struct class *myclass;

static ssize_t mydevice_show(struct device *dev, struct device_attribute *attr,
        char *buf)
{
    return sprintf(buf, "%s\n", mybuf);
}
static ssize_t mydevice_store(struct device *dev, struct device_attribute *attr,
         const char *buf, size_t count)
{
    sprintf(mybuf, "%s", buf);

    return count;
}
static DEVICE_ATTR(mydevice, 0644, mydevice_show, mydevice_store);

static struct file_operations myfops = {
    .owner = THIS_MODULE,
};

int __init mydevice_init(void)
{
    int ret;
    struct device *mydevice;
    
    major = register_chrdev(0, "mydevice", &myfops);
    if (major < 0) {
        ret = major;
        return ret;
    }
    
    myclass = class_create(THIS_MODULE, "myclass");
    if (IS_ERR(myclass)) {
        ret = -EBUSY;
        goto fail;
    }
    
    mydevice = device_create(myclass, NULL, MKDEV(major, 0), NULL, "mydevice");
    if (IS_ERR(mydevice)) {
        class_destroy(myclass);
        ret = -EBUSY;
        goto fail;
    }

    ret = sysfs_create_file(&mydevice->kobj, &dev_attr_mydevice.attr);
    if (ret < 0)
        return ret;

    return 0;

fail:
    unregister_chrdev(major, "mydevice");
    return ret;
}

void __exit mydevice_exit(void)
{
    device_destroy(myclass, MKDEV(major, 0));
    class_destroy(myclass);
    unregister_chrdev(major, "mydevice");
}

module_init(mydevice_init);
module_exit(mydevice_exit);

MODULE_DESCRIPTION("A simplest driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("HLY");

 

4, the test results

After compiling the driver, the driver module to load and view files created out of the property, the use of cat and echo commands to read and write tests:

# make
# insmod simple-device.ko
# cd /sys/devices/virtual/myclass/mydevice/
# ls –al ./

The results shown below, you can see out of the property to create a file mydevice:

Next, use cat and echo commands for file reading and writing tests:

# cat mydevice
# echo "I am a simplest driver." > mydevice
# cat mydevice

Run results are shown below, it can be seen cat and echo can be used to read and write commands normally a file attribute:

 

5, subsection

This paper briefly introduces the implementation of the Linux kernel DEVICE_ATTR macro and use a simple driver examples to explain how to use macros in DEVICE_ATTR Linux driver and the realization of the properties file read and write functions.

 

reference:

https://blog.csdn.net/hpu11/article/details/83113729

https://blog.csdn.net/DLUTBruceZhang/article/details/8658475

Guess you like

Origin www.cnblogs.com/Cqlismy/p/11454573.html