/sysfs is one of the most popular kernel to user-space interface which you can leverage to add an interface to your Kernel code such as Kernel modules, Kernel Device Drivers, etc. Although personally I prefer /proc interface than other alternatives such as /sysfs, ioctl() and so on for my personal Kernel modules/stack.
So here is my detailed multi-episode Youtube video series on /sysfs Interface.
Here is my sample source-code discussed in the video:
/* sysfs_example.c
* Author: Kiran Kankipati
* Updated: 14-May-2022
* Release notes: this is the first version of Sample /sysfs read access file.
* compatible with: 5.13.0-41-generic (Ubuntu 21.10) - as well tested with: 5.15.0-27-generic (Ubuntu 22.04 LTS)
*/
//file at: /sys/kernel/my_sysfs/my_sysfs_file
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/inet.h>
#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/icmp.h>
#include <linux/proc_fs.h>
#include <linux/netlink.h>
#include <linux/mroute.h>
#include <net/checksum.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
#include <net/route.h>
#include <net/sock.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <net/arp.h>
#include <net/udp.h>
#include <net/icmp.h>
#include <net/inetpeer.h>
#include <net/protocol.h>
#include <net/flow.h>
#include <asm/types.h>
#include <asm/string.h>
static struct kobject *register_kobj;
static char *sysfs_buf;
#define SYSFS_BUF_MAX_SIZE 1024
static ssize_t sysfs_read_value(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{ return sprintf(buf, "%s\n", sysfs_buf); }
static ssize_t __used sysfs_write_value(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{ strcpy(sysfs_buf, buf); return count; }
static struct kobj_attribute sysfs_val_attribute = __ATTR( my_sysfs_file, 0660, sysfs_read_value, sysfs_write_value);
static int sysfs_module_init(void)
{
sysfs_buf = kzalloc(SYSFS_BUF_MAX_SIZE, GFP_KERNEL); if(sysfs_buf==NULL) { return 0; }
register_kobj = kobject_create_and_add("my_sysfs", kernel_kobj); { if(!register_kobj) { return -ENOMEM; } }
if(sysfs_create_file(register_kobj, &sysfs_val_attribute.attr)) { printk("failed to create the my_sysfs_file file in /sys/kernel/my_sysfs/my_sysfs_file \n"); }
return 0;
}
static void sysfs_module_exit(void)
{
kfree(sysfs_buf);
kobject_put(register_kobj);
}
module_init(sysfs_module_init);
module_exit(sysfs_module_exit);
MODULE_DESCRIPTION("Sample /sysfs read/write access file");
MODULE_AUTHOR("Copyright(c) 2022 - Kiran Kankipati");
MODULE_LICENSE("GPL v2");
Its makefile:
obj-m += sysfs_example.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules