title:Create sysfs entry keywords:kernel,linux,threads # Create sysfs entry ## 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 /* Needed by all modules */ #include 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 /* Needed by all modules */ #include 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 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/