diff options
Diffstat (limited to 'md/notes/kernel')
-rw-r--r-- | md/notes/kernel/create_sysfs_entry.md | 247 |
1 files changed, 246 insertions, 1 deletions
diff --git a/md/notes/kernel/create_sysfs_entry.md b/md/notes/kernel/create_sysfs_entry.md index 2af3cca..529930a 100644 --- a/md/notes/kernel/create_sysfs_entry.md +++ b/md/notes/kernel/create_sysfs_entry.md @@ -5,6 +5,250 @@ keywords:kernel,linux,threads ## Starting point +__Makefile__ +```Makefile +obj-m += sysfs_entry.o + +KDIR ?= /lib/modules/$(shell uname -r)/build + +all: + make -C $(KDIR) M=$(PWD) modules + +clean: + make -C $(KDIR) M=$(PWD) clean +``` + +__sysfs_entry.c__ +```c +#include <linux/module.h> /* Needed by all modules */ +#include <linux/kernel.h> + +int sysfs_entry_init( void ) +{ + printk(KERN_DEBUG "Hello Sysfs!\n"); + return 0; +} + +void sysfs_entry_exit( void ) +{ + printk(KERN_DEBUG "Exit Sysfs!\n"); +} + +module_init( sysfs_entry_init ); +module_exit( sysfs_entry_exit ); + +MODULE_LICENSE("GPL"); +``` + +## Creating entries + +### Kobject structure + +```c +struct kobject { + const char *name; + struct list_head entry; + struct kobject *parent; + struct kset *kset; + const struct kobj_type *ktype; + struct kernfs_node *sd; /* sysfs directory entry */ + struct kref kref; +#ifdef CONFIG_DEBUG_KOBJECT_RELEASE + struct delayed_work release; +#endif + unsigned int state_initialized:1; + unsigned int state_in_sysfs:1; + unsigned int state_add_uevent_sent:1; + unsigned int state_remove_uevent_sent:1; + unsigned int uevent_suppress:1; +}; +``` + +### Add entry to /sys/kernel + +__sysfs_entry.c__ +```c +struct kobject *sysfs_kobj; + +int sysfs_entry_init( void ) +{ + ... + + sysfs_kobj = kobject_create_and_add("secret", kernel_kobj); + + ... + return 0; +} + +void sysfs_entry_exit( void ) +{ + ... + + kobject_put(sysfs_kobj); +} + +``` + +When loading module with +```sh +sudo insmod sysfs_entry.ko +``` + +There should be new directory under /sys/kernel called secret. + +### Add file under the directory + +__sysfs_entry.c__ +```c + +... +volatile int secret_value; + +struct kobject *sysfs_kobj; +struct kobj_attribute secret_attr = __ATTR(secret_value, 0660, NULL, NULL); +... + +int sysfs_entry_init( void ) +{ + ... + + if(sysfs_create_file(sysfs_kobj, &secret_attr.attr)) { + pr_err("Cant create secret file"); + } + + + ... + return 0; +} + +void sysfs_entry_exit( void ) +{ + ... + sysfs_remove_file(sysfs_kobj, &secret_attr.attr); + ... + +} +``` + +Now we are able to find secret_value file and attempt to read values + +```sh +sudo cat /sys/kernel/secret/secret_value +cat: /sys/kernel/secret/secret_value: Input/output error +``` + +### Read write value from the syfs entry + +__sysfs_entry.c__ +```c +... +static ssize_t secret_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { + printk(KERN_DEBUG "Show value %d\n", secret_value); + return sprintf(buf, "%d", secret_value); +} + +static ssize_t secret_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count) { + printk(KERN_DEBUG "Set value %s %ldd\n", buf, count); + sscanf(buf, "%d", &secret_value); + return count; +} + +struct kobj_attribute secret_attr = __ATTR(secret_value, 0660, secret_show, secret_store); +... + +int sysfs_entry_init( void ) +{ + ... + + ... + return 0; +} + +void sysfs_entry_exit( void ) +{ + ... + sysfs_remove_file(sysfs_kobj, &secret_attr.attr); + kobject_put(sysfs_kobj); + ... +} +``` + +Now we are able to set and read values from sys file + + +```sh +sudo cat /sys/kernel/secret/secret_value +``` +or +```sh +echo 1 | sudo tee -a /sys/kernel/secret/secret_value +``` + +## List of functions used + +| Function name | Note | +|---|---| +| kobject_create_and_add | | +| sysfs_create_file | | +| sysfs_remove_file | | +| kobject_put | | +| | | + + + +## Final result + +__sysfs_entry.c__ +```c +#include <linux/module.h> /* Needed by all modules */ +#include <linux/kernel.h> + +volatile int secret_value; + +struct kobject *sysfs_kobj; + +static ssize_t secret_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { + printk(KERN_DEBUG "Show value %d\n", secret_value); + return sprintf(buf, "%d", secret_value); +} + + +static ssize_t secret_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count) { + printk(KERN_DEBUG "Set value %s %ldd\n", buf, count); + sscanf(buf, "%d", &secret_value); + return count; +} + +struct kobj_attribute secret_attr = __ATTR(secret_value, 0660, secret_show, secret_store); + + +int sysfs_entry_init( void ) +{ + printk(KERN_DEBUG "Hello Syscfs!\n"); + + sysfs_kobj = kobject_create_and_add("secret", kernel_kobj); + + if(sysfs_create_file(sysfs_kobj, &secret_attr.attr)) { + pr_err("Cant create secret file"); + } + + return 0; +} + +void sysfs_entry_exit( void ) +{ + printk(KERN_DEBUG "Exit Sysfs!\n"); + + sysfs_remove_file(sysfs_kobj, &secret_attr.attr); + kobject_put(sysfs_kobj); +} + +module_init( sysfs_entry_init ); +module_exit( sysfs_entry_exit ); + +MODULE_LICENSE("GPL"); + +``` ## Links @@ -12,5 +256,6 @@ https://man7.org/linux/man-pages/man5/sysfs.5.html https://embetronicx.com/tutorials/linux/device-drivers/sysfs-in-linux-kernel/ https://elixir.bootlin.com/linux/v6.1.64/source/include/linux/sysfs.h https://docs.kernel.org/filesystems/sysfs.html - +https://elixir.bootlin.com/linux/v6.1.64/source/include/linux/kobject.h#L64 +https://pradheepshrinivasan.github.io/2015/07/02/Creating-an-simple-sysfs/ |