2025-03-18
Linux的sysfs是一种虚拟文件系统,用于将内核对象、属性和关系导出到用户空间,方便用户和管理员查看和配置内核及硬件信息。sysfs通常挂载在/sys
目录下。
sysfs class
是sysfs中的一个重要部分,用于按功能分类展示设备信息。每个类对应一种设备类型(如网络设备、输入设备等),类目录下包含该类设备的子目录,每个子目录代表一个具体设备,包含其属性和相关链接。
sysfs class
net: 网络设备信息。
input: 输入设备(如键盘、鼠标)信息。
block: 块设备(如硬盘、分区)信息。
tty: 串行设备信息。
drm: 图形设备信息。
sound: 音频设备信息。
// simple.c
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/slab.h>
#define DEV_NAME "my-dev"
#define CLASS_NAME "my-class"
static dev_t dev_nr;
static struct class *my_class;
static struct device *my_dev;
static int answer = 42;
DEVICE_INT_ATTR(answer, 0600, answer);
static char text[64] = "Hello World!\n";
static ssize_t text_store(struct device *dev, struct device_attribute *attr,
const char *buffer, size_t size) {
pr_info("simple_text_store\n");
memset(text, 0, sizeof(text));
size = min(size, sizeof(text));
strncpy(text, buffer, size);
return size;
}
static ssize_t text_show(struct device *dev, struct device_attribute *attr,
char *buffer) {
pr_info("simple_text_show\n");
strcpy(buffer, text);
return strlen(text);
}
DEVICE_ATTR(text, 0600, text_show, text_store);
static int __init simple_init(void) {
pr_info("simple_init\n");
int status = alloc_chrdev_region(&dev_nr, 0, MINORMASK + 1, DEV_NAME);
if (status < 0) {
pr_err("alloc_chrdev_region error\n");
return status;
}
my_class = class_create(CLASS_NAME);
if (IS_ERR(my_class)) {
pr_err("class_create error\n");
status = PTR_ERR(my_class);
goto free_dev_nr;
}
my_dev =
device_create(my_class, NULL, dev_nr, NULL, DEV_NAME"%d", MINOR(dev_nr));
if (IS_ERR(my_dev)) {
pr_err("device_create error\n");
status = PTR_ERR(my_dev);
goto free_class;
}
status = device_create_file(my_dev, &dev_attr_text);
if (status) {
pr_err("device_create_file for text error\n");
goto free_dev;
}
status = device_create_file(my_dev, &dev_attr_answer.attr);
if (status) {
pr_err("device_create_file for answer error\n");
goto free_text;
}
return 0;
free_text:
device_remove_file(my_dev, &dev_attr_text);
free_dev:
device_destroy(my_class, dev_nr);
free_class:
class_destroy(my_class);
free_dev_nr:
unregister_chrdev_region(dev_nr, MINORMASK + 1);
return status;
}
static void __exit simple_exit(void) {
pr_info("simple_exit\n");
device_remove_file(my_dev, &dev_attr_answer.attr);
device_remove_file(my_dev, &dev_attr_text);
device_destroy(my_class, dev_nr);
class_destroy(my_class);
unregister_chrdev_region(dev_nr, MINORMASK + 1);
}
module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple kernel module");
#!/bin/sh
top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build
obj-m += simple.o
all:
make -C $(kernel-dir) modules M=$(top-dir)
clean:
rm -f *.o *.ko *.mod *.mod.c *.order *.symvers *.dtbo
make -C $(kernel-dir) clean m=$(top-dir)
编译程序:make
安装驱动:insmod simple.ko
查看文件:ls /sys/class/my-class/my-dev0
answer dev power subsystem text uevent
读取数据:cat /sys/class/my-class/my-dev0/text
写入数据:echo "good" > /sys/class/my-class/my-dev0/text
移除驱动:rmmod simple.ko