Kernel module options in sysfs - quick response to changes

Is it possible to notify the module when one of them sys files was changed? My task is to make a file that controls the size of the buffer inside the module, I want to change the size of the buffer when the value in the file changes. My other idea (if I cannot notify the module) was to check the previous value each time the module was used, and then resize the buffer.

+4
source share
1 answer

Isn't that the purpose of Sysfs?

When you create a kobject and provide it with a view in Sysfs (this is a directory), you then create attributes for this object that will become files in this directory. You provide a store and show kobject for kobject , which are basically equivalent respectively. write and read .

store is what you want here. It looks like this:

 ssize_t (*store)(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size); 

You get size bytes within buffer as soon as the virtual file is written to the user's land.

Take a look at this module that does this (taken from here ):

 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/slab.h> struct my_attr { struct attribute attr; int value; }; static struct my_attr my_first = { .attr.name="first", .attr.mode = 0644, .value = 1, }; static struct my_attr my_second = { .attr.name="second", .attr.mode = 0644, .value = 2, }; static struct attribute * myattr[] = { &my_first.attr, &my_second.attr, NULL }; static ssize_t default_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct my_attr *a = container_of(attr, struct my_attr, attr); return scnprintf(buf, PAGE_SIZE, "%d\n", a->value); } static ssize_t default_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) { struct my_attr *a = container_of(attr, struct my_attr, attr); sscanf(buf, "%d", &a->value); return sizeof(int); } static struct sysfs_ops myops = { .show = default_show, .store = default_store, }; static struct kobj_type mytype = { .sysfs_ops = &myops, .default_attrs = myattr, }; struct kobject *mykobj; static int __init sysfsexample_module_init(void) { int err = -1; mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL); if (mykobj) { kobject_init(mykobj, &mytype); if (kobject_add(mykobj, NULL, "%s", "sysfs_sample")) { err = -1; printk("Sysfs creation failed\n"); kobject_put(mykobj); mykobj = NULL; } err = 0; } return err; } static void __exit sysfsexample_module_exit(void) { if (mykobj) { kobject_put(mykobj); kfree(mykobj); } } module_init(sysfsexample_module_init); module_exit(sysfsexample_module_exit); MODULE_LICENSE("GPL"); 

Also : you may want to display the size of the buffer to the user when the record is read. This is usually a way to do this. Also make sure that the information (read and written) is in a human-friendly format so as not to lag behind the Unix philosophy.

Update : see this recent interesting article about creating a Sysfs file written by Greg Croach-Hartman, one of the kernel developers.

+9
source

All Articles