Skip to content

sysfs Attributes

Sysfs Attribute Implementation

Sysfs attributes provide a structured way to expose device-specific parameters and status to user space. This section demonstrates how to implement sysfs attributes in a kernel module, enabling read/write access to device data.

Core Concepts

Sysfs attributes are implemented using the struct device_attribute and associated show()/store() functions. Each attribute corresponds to a file in the sysfs filesystem, typically under /sys/class/... or /sys/devices/....

Key components: - Attribute structure: Defines the name, permissions, and callbacks. - Show function: Called on cat <filename>. - Store function: Called on echo <value> > <filename>. - Sysfs registration: Uses sysfs_create_file() to link the attribute to a device.

Implementation Steps

  1. Define the attribute structure
    Use __ATTR() macro or manually define struct device_attribute with:
  2. name: Attribute filename (e.g., temp)
  3. mode: Permissions (e.g., 0644 for rw for owner)
  4. show: Pointer to read function
  5. store: Pointer to write function

  6. Implement show() and store()
    These functions must be thread-safe and handle concurrent access. Example:

    ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) {
        return sprintf(buf, "%d\n", temp_value);
    }
    
    ssize_t store_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
        int val;
        if (sscanf(buf, "%d", &val) == 1)
            temp_value = val;
        return count;
    }
    

  7. Register the attribute
    During module initialization, associate the attribute with a struct device:

    sysfs_create_file(&my_dev->kobj, &my_attr.attr);
    
    Ensure the device is properly registered (e.g., via device_create()).

  8. Cleanup on module exit
    Remove the sysfs entry and destroy the device:

    sysfs_remove_file(&my_dev->kobj, &my_attr.attr);
    device_destroy(my_class, MKDEV(MY_MAJOR, 0));
    

Example: Temperature Sensor Attribute

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/device.h>

static struct device *my_dev;
static int temp_value = 42;

static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) {
    return sprintf(buf, "%d\n", temp_value);
}

static ssize_t store_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
    int val;
    if (sscanf(buf, "%d", &val) == 1)
        temp_value = val;
    return count;
}

static struct device_attribute my_attr = __ATTR(temp, 0644, show_temp, store_temp);

static int __init my_init(void) {
    my_dev = device_create(NULL, NULL, MKDEV(0, 0), NULL, "my_device");
    sysfs_create_file(&my_dev->kobj, &my_attr.attr);
    return 0;
}

static void __exit my_exit(void) {
    sysfs_remove_file(&my_dev->kobj, &my_attr.attr);
    device_destroy(NULL, MKDEV(0, 0));
}

module_init(my_init);
module_exit(my_exit);

Key Takeaways

  • Attribute structure: Use __ATTR() or manually define struct device_attribute with show()/store() callbacks.
  • Sysfs registration: Link attributes to a struct device using sysfs_create_file().
  • Thread safety: Ensure show()/store() handle concurrent access and validate input.
  • Cleanup: Always remove sysfs entries and destroy devices during module exit to avoid memory leaks.