sysfs统一设备模型
文章目录
- 1、前言
- 2、sysfs设备文件系统
- 3、kobject、kset、kobj_type 介绍
- 4、驱动程序编写
- 5、测试
- 6、总结
1、前言
参考书籍及本文部分图片来源:作者李文山的《linux驱动开发入门》https://gitee.com/li-shan-asked/linux-develop-guide
2、sysfs设备文件系统
sysfs是一个基于RAM的虚拟文件系统,从Linux 2.6内核版本开始被引入。它的主要作用是以文件目录的形式向用户空间导出内核对象(如设备、驱动程序等)的数据和属性。sysfs使得用户空间的程序能够动态地获取和管理系统中的设备信息,而无需直接访问内核数据结构。
sysfs 设备文件系统与 udev、proc 以及 devpty 是同一类别的文件系统,该文件系统是一个虚拟的文件系统,sysfs 是一种基于 ramfs 实现的内存文件系统。在开发板中进入/sys 目录下,查看其内容如下:
- block 目录:包含所有的块设备;
- class 目录:包含所有的设备类;
- devices 目录:包含所有存在的设备;
- fs 目录:包含了当前内核挂载的所有文件系统;
- module 目录:包含了内核挂载了所有模块;
- bus 目录:包含了内核中所有的总线设备类型;
- dev 目录:该目录下有两个目录,分别是 block 和 char 目录,该目录包含了所有的 /sys/devices 目录中所有设备的设备号信息;
- fireware 目录:包含对固件对象(firmware object) 和属性进行操作和观察的接口,即这里是系统加载固件机制的对用户空间的接口(关于固件有专用于固件加载的一套 API);
- kernel 目录:存放当前内核版本所有可以更改的参数;
- power 目录:包含所有电源管理的文件,用户可以通过对该目录下的文件进行读写来控制系统电源。
如我们常见的在用户态通过控制/sys/class/gpio目录下的属性来控制gpio:
3、kobject、kset、kobj_type 介绍
可以参考上述介绍的书籍。
4、驱动程序编写
下面以led程序为例,展示sysfs的应用。驱动程序并未控制实际led,只作打印:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/string.h>
static struct kobject *led_kobj;
static int led_status = 0;
static ssize_t led_show(struct kobject* kobjs,struct kobj_attribute *attr,char *buf)
{
printk(KERN_INFO "Read led\n");
return sprintf(buf, "%d\n", led_status);
}
static ssize_t led_store(struct kobject *kobj, struct kobj_attribute *attr,const char
*buf, size_t count)
{
printk(KERN_INFO "led status store\n");
if(0 == memcmp(buf, "on", 2))
{
led_status = 1;
}
else if(0 == memcmp(buf, "off", 3))
{
led_status = 0;
}
else
{
printk(KERN_INFO "Not support cmd\n");
}
return 1;
}
/* 创建一个名为"led_status"的属性,指定show和store函数 */
static struct kobj_attribute led_attr = {
.attr.name = "led_status",
.attr.mode = 0660,
.show = led_show,
.store = led_store,
};
static int __init sysfs_led_init(void)
{
int ret;
/* 1、创建led_kobj对象,也就是会在/sys目录下生成一个"sys_led"文件夹 */
led_kobj = kobject_create_and_add("sys_led", NULL);
if(led_kobj == NULL)
{
printk(KERN_INFO"create led_kobj failed!\n");
return -1;
}
/* 2、为led_kobj创建属性,也就是会在/sys/sys_led目录下创建一个"led_status"属性 */
ret = sysfs_create_file(led_kobj, &led_attr.attr);
if(ret != 0)
{
printk(KERN_INFO"create sysfa file failed!\n");
return -1;
}
return 0;
}
static void __exit sysfs_led_exit(void)
{
sysfs_remove_file(led_kobj, &led_attr.attr);
kobject_put(led_kobj);
printk(KERN_INFO "exit sysfs led!\n");
}
module_init(sysfs_led_init);
module_exit(sysfs_led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("1033878279@qq.com");
MODULE_DESCRIPTION("sysfs led");
MODULE_VERSION("0.1");
5、测试
1、加载驱动程序:
insmod sysfs_led_drv.ko
2、进入/sys目录查看,发现已经创建sys_led目录:
3、进入/sys/sys_led目录,控制led:
cd /sys/sys_led
# 查看设置前的led状态
cat led_status
# 使能led
echo on > led_status
cat led_status
# 关闭led
echo off > led_status
cat led_status
6、总结
主要了解sysfs统一设备模型概念等知识,进行简单的驱动程序编写。