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¶
- Define the attribute structure
Use__ATTR()macro or manually definestruct device_attributewith: name: Attribute filename (e.g.,temp)mode: Permissions (e.g.,0644for rw for owner)show: Pointer to read function-
store: Pointer to write function -
Implement
show()andstore()
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; } -
Register the attribute
Ensure the device is properly registered (e.g., via
During module initialization, associate the attribute with astruct device:device_create()). -
Cleanup on module exit
Remove the sysfs entry and destroy the device:
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 definestruct device_attributewithshow()/store()callbacks. - Sysfs registration: Link attributes to a
struct deviceusingsysfs_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.