当前位置: 首页 > article >正文

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统一设备模型概念等知识,进行简单的驱动程序编写。


http://www.kler.cn/a/550306.html

相关文章:

  • MATLAB中regexpi函数用法
  • 使用OBS和nginx实现直播流
  • 深入解析 iOS 视频录制(一):录制管理核心MWRecordingController 类的设计与实现
  • Java基于 SpringBoot+Vue的微信小程序跑腿平台V2.0(附源码,文档)
  • Fisco-Bcos单群组区块链部署
  • 浏览器跨标签页通信
  • 【火星】火星 数字地面模型(DEM)数字正射影像(DOM)下载
  • POI 和 EasyExcel
  • Hadoop基本介绍
  • 【信息学奥赛一本通 C++题解】1285:最大上升子序列和
  • 数据结构(查找)
  • 浅析 vue里的全局指令文件 directives
  • 第1章大型互联网公司的基础架构——1.3 HTTP-DNS
  • 大模型知识蒸馏:解析原理、谈DeepSeek及服务器适配思路
  • 宝藏软件系列 篇一:My APK(Android)
  • Copilot:Excel中的Python高级分析来了
  • 青少年编程与数学 02-009 Django 5 Web 编程 19课题、RESTful API开发
  • C语言基础16:二维数组、字符数组
  • Mac本地部署deepseek
  • uv 简易安装与更换国内镜像源