How to create a simple sysfs class attribute in Linux kernel v3.2

Vilhelm Gray picture Vilhelm Gray · Apr 26, 2013 · Viewed 28k times · Source

I'm learning how to use sysfs in my Linux modules, but I'm having the hardest time finding current documentation on these topics. The Linux Device Drivers 3rd Edition book I've been using seems to be rather dated in this area unfortunately (e.g. the class_device structure appears to be completely gone in current Linux versions).

I'm simply trying to get an attribute to appear, under the respective sysfs class for my module, that will allow me to read the value of a module variable from kernel space.

In my code, I have a class created that allows udev to create a device node at /dev/foo for my module:

dev_t foo_dev;
alloc_chrdev_region(&foo_dev, 0, 1, "bar");

struct class *bar = class_create(THIS_MODULE, "bar");

device_create(bar, NULL, foo_dev, NULL, "foo");

struct cdev foo_dev_file;
cdev_init(&foo_dev_file, &fops); /* fops defined earlier */
cdev_add(&foo_dev_file, foo_dev, 1);

When I insert the module I get a sysfs class directory created and populated with some default attributes at /sys/class/bar/foo/. How can I create attributes that show up under this new directory?

I have the concepts down pretty well I believe -- create attribute structure, define sysfs_ops functions, etc -- my problem is that I don't know which particular kernel structure to use (class_attribute?), nor how to make these attributes appear under the right sysfs directory.

Would anyone point me to a tutorial or article detailing the process for current Linux kernels?

Answer

Daniel Santos picture Daniel Santos · Apr 27, 2013

Even though my knowledge is still fairly low on the topic, I'm going to post an answer just because of the age of this question. If somebody else has a better answer, please post! :)

First off, I'm going to assume that you've read that whole chapter (specifically about kobjects & ksets). So just about every struct in the device driver model has these cutely included in them. If you want to manipulate the kobject for the class its self (not sure if that's wise or not), that's your struct class's dev_kobj member.

However, you want to manipulate the attributes of that class. I believe you do this by defining a (usually static), NULL-terminated array of them as follows and then assigning its address to the struct class's class_attrs member (taken from drivers/uwb/driver.c):

static struct class_attribute uwb_class_attrs[] = {
    __ATTR(beacon_timeout_ms, S_IWUSR | S_IRUGO,
           beacon_timeout_ms_show, beacon_timeout_ms_store),
    __ATTR_NULL,
};

/** Device model classes */
struct class uwb_rc_class = {
    .name        = "uwb_rc",
    .class_attrs = uwb_class_attrs,
};

When I don't know how to use something, I usually git grep the repository for somebody else who has used it and try to learn from it that way. It would seem that this is why they tend to say kernel "hackers" and not "developers".