LINUX sysfs的使用方法举例
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;
// 创建 kobject
testdrv_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);
// 删除 kobject
kobject_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 128
static 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;
// 创建 kobject
strdrv_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);
// 删除 kobject
kobject_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