1,sysfs常用到的sys目录:
/sys/devices:表示系统中的物理设备,每个子目录对应一个设备。
/sys/class:表示系统中的设备类别(如网络设备、块设备等),子目录按类别分类。
/sys/block:表示块设备(如硬盘、USB存储设备等)。
/sys/bus:表示系统总线类型(如PCI、USB等),每个子目录对应一个总线。
/sys/kernel:表示内核参数和信息,如调度器参数、内核模块等。
/sys/module:表示加载的内核模块,每个子目录对应一个模块,包含模块参数和状态信息。
代码举例:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>#define TESTDRV_NAME "testdrv"static int test_value = 42; // 初始化一个全局变量// sysfs 读取回调函数
static ssize_t testdrv_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{return sprintf(buf, "%d\n", test_value);
}// sysfs 写入回调函数
static ssize_t testdrv_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{int ret;ret = sscanf(buf, "%du", &test_value); // 读取用户输入的值if (ret != 1)return -EINVAL; // 如果转换失败,返回错误return count; // 返回写入的字节数
}// 定义 sysfs 属性
static struct kobj_attribute testdrv_attr = __ATTR(test_value, 0664, testdrv_show, testdrv_store);// 定义 kobject 和 kset
static struct kobject *testdrv_kobj;static int __init testdrv_init(void)
{int ret;// 创建 kobjecttestdrv_kobj = kobject_create_and_add(TESTDRV_NAME, kernel_kobj);if (!mydrv_kobj) {pr_err("Failed to create kobject\n");return -ENOMEM;}// 创建 sysfs 属性ret = sysfs_create_file(testdrv_kobj, &testdrv_attr.attr);if (ret) {pr_err("Failed to create sysfs file\n");kobject_put(testdrv_kobj);return ret;}return 0;
}static void __exit testdrv_exit(void)
{// 删除 sysfs 属性sysfs_remove_file(testdrv_kobj, &testdrv_attr.attr);// 删除 kobjectkobject_put(mydrv_kobj);
}module_init(mydrv_init);
module_exit(testdrv_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple sysfs example module");
代码运行:
root@ubuntu:/home/lark/share/driver/day6/sysfs# make
make -C /lib/modules/5.15.0-125-generic/build/ M=/home/lark/share/driver/day6/sysfs modules
make[1]: Entering directory '/usr/src/linux-headers-5.15.0-125-generic'
CC [M] /home/lark/share/driver/day6/sysfs/sysfs.o
MODPOST /home/lark/share/driver/day6/sysfs/Module.symvers
CC [M] /home/lark/share/driver/day6/sysfs/sysfs.mod.o
LD [M] /home/lark/share/driver/day6/sysfs/sysfs.ko
BTF [M] /home/lark/share/driver/day6/sysfs/sysfs.ko
Skipping BTF generation for /home/lark/share/driver/day6/sysfs/sysfs.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-5.15.0-125-generic'
root@ubuntu:/home/lark/share/driver/day6/sysfs#
root@ubuntu:/home/lark/share/driver/day6/sysfs#
root@ubuntu:/home/lark/share/driver/day6/sysfs# ls
Makefile modules.order Module.symvers sysfs.c sysfs.ko sysfs.mod sysfs.mod.c sysfs.mod.o sysfs.o
root@ubuntu:/home/lark/share/driver/day6/sysfs# insmod sysfs.ko
root@ubuntu:/home/lark/share/driver/day6/sysfs# lsmod | grep sysfs
sysfs 16384 0
测试代码:
root@ubuntu:/sys/kernel/testdrv# ls
test_value
root@ubuntu:/sys/kernel/testdrv# cat test_value
42
root@ubuntu:/sys/kernel/testdrv# echo 1 > test_value
root@ubuntu:/sys/kernel/testdrv# cat test_value
1
2,字符串举例:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
#include <linux/string.h>#define STRDRV_NAME "testdrv"
#define STRDRV_ATTR_NAME "test_string"
#define STRDRV_ATTR_SIZE 128static char test_string[STRDRV_ATTR_SIZE] = "Hello, World!"; // 初始化一个全局字符串变量// sysfs 读取回调函数
static ssize_t testdrv_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{return scnprintf(buf, STRDRV_ATTR_SIZE, "%s\n", test_string);
}// sysfs 写入回调函数
static ssize_t testdrv_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{if (count >= STRDRV_ATTR_SIZE) {return -EINVAL; // 如果写入的数据太长,返回错误}strncpy(test_string, buf, count); // 复制用户输入的字符串test_string[count - 1] = '\0'; // 确保字符串以空字符结尾return count; // 返回写入的字节数
}// 定义 sysfs 属性
static struct kobj_attribute testdrv_attr = __ATTR(test_string, 0664, testdrv_show, testdrv_store);// 定义 kobject
static struct kobject *strdrv_kobj;static int __init strdrv_init(void)
{int ret;// 创建 kobjectstrdrv_kobj = kobject_create_and_add(STRDRV_NAME, kernel_kobj);if (!strdrv_kobj) {pr_err("Failed to create kobject\n");return -ENOMEM;}// 创建 sysfs 属性ret = sysfs_create_file(strdrv_kobj, &testdrv_attr.attr);if (ret) {pr_err("Failed to create sysfs file\n");kobject_put(strdrv_kobj);return ret;}return 0;
}static void __exit strdrv_exit(void)
{// 删除 sysfs 属性sysfs_remove_file(strdrv_kobj, &testdrv_attr.attr);// 删除 kobjectkobject_put(strdrv_kobj);
}module_init(strdrv_init);
module_exit(strdrv_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple sysfs example module for a string attribute");
测试代码 :
root@ubuntu:/sys/kernel/testdrv# cat test_string
Hello, World!
root@ubuntu:/sys/kernel/testdrv#
root@ubuntu:/sys/kernel/testdrv# echo welcome > test_string
root@ubuntu:/sys/kernel/testdrv#
root@ubuntu:/sys/kernel/testdrv# cat test_string
welcome