Linux 的 sysfs 伪文件系统介绍【用户可以通过文件操作与内核交互(如调用内核函数),而无需编写内核代码】
1. 什么是 sysfs伪文件系统?
sysfs
是 Linux 内核提供的 伪文件系统,用于向用户空间暴露内核对象的信息和控制接口。它是 procfs
的补充,主要用于管理 设备、驱动、内核子系统 等信息,使用户可以通过文件操作(如用户空间中的open函数、write函数、read函数、 cat
命令、echo
命令)与内核交互【对文件的操作其实直接转换为调用相应的内核函数】,而无需编写内核代码。
- 挂载位置:通常挂载在
/sys
目录下。 - 作用:
- 提供系统信息(如 CPU、设备、驱动程序、总线)。
- 提供设备控制接口(如 GPIO、PWM、I2C、SPI 等)。
- 支持热插拔设备管理(如 USB、PCI、SATA 设备)。
sysfs伪文件系统实际上和设备文件很类似,它们都是用户空间与内核空间交互的媒介,不同的是设备文件是内核空间中驱动程序中的概念,而sysfs伪文件系统则是内核空间中别的需要向用户空间暴露的内核对象的信息和控制接口。所以它的使用实际上和设备文件很类似。
在终端中使用sysfs伪文件系统时,表面上我们是在用相关函数或cat
、echo
命令进行读或写相关的文件,实际上会转换为对某个内核函数的调用。具体的例子见本篇博文后面列出的“一个实际的例子分析”
而在程序代码中使用sysfs伪文件系统时,就和操作设备文件差不多。具体的例子见 https://blog.csdn.net/wenhao_ir/article/details/145459006【搜索“led_init(void)”】
2. sysfs 的目录结构
sysfs 目录下的结构主要分为以下几部分:
/sys/├── block/ # 块设备(如磁盘、分区)├── bus/ # 设备总线(如 i2c, usb, spi, pci, platform)├── class/ # 设备类(如 gpio, net, tty, input)├── devices/ # 设备层次结构├── firmware/ # 固件接口├── kernel/ # 内核参数├── module/ # 加载的内核模块└── power/ # 电源管理
3. sysfs 目录详解
(1)/sys/class/
-
组织 设备 按类别分类(如 GPIO、网络、输入设备)。
-
例子:
ls /sys/class/
输出:
gpio/ net/ input/ sound/ thermal/ tty/ usb_device/
-
GPIO 设备(使用 sysfs 方式操作 GPIO)
echo 131 > /sys/class/gpio/export # 申请 GPIO 131 echo out > /sys/class/gpio/gpio131/direction # 设置方向 echo 1 > /sys/class/gpio/gpio131/value # 设为高电平
我后面会对这三句命令作详细解释,其实就是以这三句命令活生生地展现 sysfs 伪文件系统是怎么实现与内核的交互的。
-
网卡信息
ls /sys/class/net/ eth0 lo wlan0
cat /sys/class/net/eth0/address
# 查看 MAC 地址cat /sys/class/net/eth0/statistics/rx_bytes
# 接收的字节数
(2)/sys/bus/
-
组织 设备按总线分类(如 PCI、USB、I2C、SPI)。
-
例子:
ls /sys/bus/
输出:
i2c/ pci/ platform/ scsi/ spi/ usb/
/sys/bus/i2c/devices/
# I2C 设备/sys/bus/usb/devices/
# USB 设备/sys/bus/pci/devices/
# PCI 设备
-
示例:列出所有 USB 设备
ls /sys/bus/usb/devices/
(3)/sys/devices/
-
按 设备拓扑结构 组织设备信息(如
/sys/devices/pci0000:00/0000:00:1f.2/
)。 -
例子:
ls /sys/devices/
system/ virtual/ pci0000:00/
-
查看 CPU 信息
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
(4)/sys/module/
- 显示 已加载的内核模块 及其参数。
- 例子:
ls /sys/module/
cat /sys/module/gpio/parameters/
cat /sys/module/usbcore/parameters/autosuspend
(5)/sys/kernel/
-
提供与 内核相关的配置信息。
-
例子:
ls /sys/kernel/
debug/ security/ tracing/
-
查看系统调试信息
cat /sys/kernel/debug/gpio
4. sysfs 的工作机制
- sysfs 由
kobject
和kset
组成:kobject
代表 内核对象(如设备、驱动)。kset
是kobject
的集合(如devices
、bus
)。
- 设备驱动注册时,sysfs 自动创建目录和文件。
- 用户空间可以通过
cat
、echo
直接访问内核数据。
示例:
设备驱动代码:
static struct class *my_class;
my_class = class_create(THIS_MODULE, "my_device");
device_create(my_class, NULL, MKDEV(200, 0), NULL, "mydev0");
sysfs 生成的目录:
/sys/class/my_device/mydev0/
5. sysfs 的优缺点
优点 | 缺点 |
---|---|
允许用户空间与内核交互 | 只能操作文本,效率低 |
结构清晰,按类别组织 | 不适用于高频操作 |
可用于设备驱动调试 | 已被 libgpiod 等替代 |
6. sysfs 与 udev、procfs 的区别
文件系统 | 作用 | 特点 |
---|---|---|
sysfs (/sys/ ) | 设备、驱动、总线信息 | 设备管理,与 kobject 相关 |
procfs (/proc/ ) | 进程、内核信息 | 进程管理,虚拟文件 |
udev (/dev/ ) | 设备文件 | 动态创建 /dev/ 设备节点 |
7. 结论
- sysfs 是 Linux 设备模型的核心部分,用于暴露设备和驱动信息。
- 用户空间可以直接
cat
读取信息,echo
进行控制,简化了驱动开发。 - sysfs 已逐渐被
libgpiod
、udev
替代,但仍然广泛使用,特别是在嵌入式系统中。
8.一个实际的例子分析
我们可以通过下面的三条命令实现将编号为131的GPIO口(GPIO5_IO03)的值设为逻辑1值,如果GPIO没有被标记为低电平有效,则逻辑1值就是物理上的高电平,否则就是物理上的低电平,在这里,我实测了一下,GPIO5_IO03
并没有被标记为低电平有效。即运行完成后在下面的原理图基础上,灯灭了。
echo 131 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio131/direction
echo 1 > /sys/class/gpio/gpio131/value
这三条命令是通过 sysfs 接口 操作 GPIO 口 131,本质上是用户空间通过 echo
命令向 sysfs 伪文件系统写入数据,触发内核的 GPIO 相关操作【实际上就是去调用内核中的相关GPIO子系统的函数】。
在看下面的分析前可以参考下博文 https://blog.csdn.net/wenhao_ir/article/details/145119224 是如何利用GPIO子系统实现LED灯的驱动的,实际上这篇博文中调用的函数也就是下面三条echo
命令触发的内核函数。
1. echo
命令与 sysfs GPIO 实现的关系
echo
命令的作用是 向文件写入内容,但当目标文件是 sysfs 文件时,写入的值会被内核的 GPIO 处理函数拦截,并执行相应的 GPIO 操作。
下面具体分析你的 echo
命令是如何作用到 GPIO 上的:
(1)导出 GPIO
echo 131 > /sys/class/gpio/export
-
作用:请求使用 GPIO 131,让内核创建
/sys/class/gpio/gpio131/
目录。 -
sysfs 机制:
echo 131 > /sys/class/gpio/export
相当于向export
文件 写入131
。- 内核中的
export_store()
处理该写入,并调用gpio_request(131, NULL)
申请 GPIO 资源。 - 申请成功后,内核会创建
/sys/class/gpio/gpio131/
目录,用于控制 GPIO 131。
-
相关的内核代码(在
drivers/gpio/gpiolib-sysfs.c
中):static ssize_t export_store(struct class *class,struct class_attribute *attr,const char *buf, size_t count) {int gpio;int ret;ret = kstrtoint(buf, 0, &gpio);if (ret)return ret;ret = gpio_request(gpio, NULL);if (ret)return ret;return count; }
(2)设置 GPIO 方向
echo out > /sys/class/gpio/gpio131/direction
-
作用:设置 GPIO 131 为 输出模式。
-
sysfs 机制:
echo out > /sys/class/gpio/gpio131/direction
相当于向direction
文件 写入字符串"out"
。gpio_direction_output(131, 0)
被调用,将 GPIO 131 配置为 输出模式(初始值 0)。- 内核 GPIO 驱动最终会调用
gpio_chip->direction_output()
这个函数,该函数是具体的 GPIO 控制器驱动 提供的,执行底层的寄存器操作,配置 GPIO 方向。
-
相关的内核代码(在
drivers/gpio/gpiolib-sysfs.c
中):static ssize_t direction_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) {struct gpio_desc *desc = dev_get_drvdata(dev);if (!strncmp(buf, "out", 3))gpiod_direction_output(desc, 0);elsegpiod_direction_input(desc);return count; }
(3)设置 GPIO 输出值
echo 1 > /sys/class/gpio/gpio131/value
-
作用:设置 GPIO 131 输出 高电平(1)。
-
sysfs 机制:
echo 1 > /sys/class/gpio/gpio131/value
向value
文件 写入"1"
。gpio_set_value(131, 1)
被调用,更新 GPIO 131 的输出电平。- 底层驱动(
gpio_chip->set()
)负责具体的寄存器操作,将 GPIO 置高。
-
相关的内核代码(在
drivers/gpio/gpiolib-sysfs.c
中):static ssize_t value_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) {struct gpio_desc *desc = dev_get_drvdata(dev);int value;if (buf[0] == '0')value = 0;elsevalue = 1;gpiod_set_value(desc, value);return count; }
2. sysfs GPIO 实现的局限
虽然 sysfs 提供了一种 简单的方式 来访问 GPIO,但它有以下局限性:
- 效率低:sysfs 通过文件操作控制 GPIO,比
ioctl
或mmap
慢。 - 无法高效处理中断:sysfs 方式不适合监听 GPIO 变化(如按键)。
- 已被
libgpiod
取代:新版本的 Linux 内核推荐使用libgpiod
(基于ioctl
的 GPIO 操作)。
3. 结论
🔹 sysfs 方式是 Linux 早期的 GPIO 控制方法,echo
命令本质上是向 sysfs 伪文件系统写入数据,触发内核调用 GPIO 操作函数。
🔹 每个 echo
命令最终都会调用 gpiolib
提供的 API,如 gpio_request()
、gpio_direction_output()
和 gpio_set_value()
,再由底层 GPIO 驱动完成实际的硬件操作。
🔹 sysfs 方式简单直观,但不适用于高效 GPIO 访问,现代 Linux 推荐使用 libgpiod
代替 sysfs GPIO
。(实际上在Linux 5.10以上版本中已经把sysfs
这种对GPIO的操作方式废弃了)
比如上面的三条命令等效于下面这条gpiod API
的命令:
gpioset gpiochip0 131=1
相关文章:

Linux 的 sysfs 伪文件系统介绍【用户可以通过文件操作与内核交互(如调用内核函数),而无需编写内核代码】
1. 什么是 sysfs伪文件系统? sysfs 是 Linux 内核提供的 伪文件系统,用于向用户空间暴露内核对象的信息和控制接口。它是 procfs 的补充,主要用于管理 设备、驱动、内核子系统 等信息,使用户可以通过文件操作(如用户空…...

每日一题洛谷P5721 【深基4.例6】数字直角三角形c++
#include<iostream> using namespace std; int main() {int n;cin >> n;int t 1;for (int i 0; i < n; i) {for (int j 0; j < n - i; j) {printf("%02d",t);t;}cout << endl;}return 0; }...

计算机网络笔记再战——理解几个经典的协议1
目录 前言 从协议是什么出发 关于TCP/IP协议体系 几个传输方式的分类 地址 网卡 中继器(Repeater) 网桥(Bridge) 路由器(Router) 网关 前言 笔者最近正在整理(笔者开的坑不少…...
ElasticSearch学习笔记-解析JSON格式的内容
如果需要屏蔽其他项目对Elasticsearch的直接访问操作,统一由一个入口访问操作Elasticsearch,可以考虑直接传入JSON格式语句解析执行。 相关依赖包 <properties><elasticsearch.version>7.9.3</elasticsearch.version><elasticsea…...

浅谈密码相关原理及代码实现
本代码仅供学习、研究、教育或合法用途。开发者明确声明其无意将该代码用于任何违法、犯罪或违反道德规范的行为。任何个人或组织在使用本代码时,需自行确保其行为符合所在国家或地区的法律法规。 开发者对任何因直接或间接使用该代码而导致的法律责任、经济损失或…...

Spring Boot常用注解深度解析:从入门到精通
今天,这篇文章带你将深入理解Spring Boot中30常用注解,通过代码示例和关系图,帮助你彻底掌握Spring核心注解的使用场景和内在联系。 一、启动类与核心注解 1.1 SpringBootApplication 组合注解: SpringBootApplication Confi…...

can not add outlook new accounts on the outlook
link : Reference url...

私有化部署 DeepSeek + Dify,构建你的专属私人 AI 助手
私有化部署 DeepSeek Dify,构建你的专属私人 AI 助手 概述 DeepSeek 是一款开创性的开源大语言模型,凭借其先进的算法架构和反思链能力,为 AI 对话交互带来了革新性的体验。通过私有化部署,你可以充分掌控数据安全和使用安全。…...

【Elasticsearch】post_filter
post_filter是 Elasticsearch 中的一种后置过滤机制,用于在查询执行完成后对结果进行过滤。以下是关于post_filter的详细介绍: 工作原理 • 查询后过滤:post_filter在查询执行完毕后对返回的文档集进行过滤。这意味着所有与查询匹配的文档都…...
验证工具:GVIM和VIM
一、定义与关系 gVim:gVim是Vim的图形界面版本,提供了更多的图形化功能,如菜单栏、工具栏和鼠标支持。它使得Vim的使用更加直观和方便,尤其对于不习惯命令行界面的用户来说。Vim:Vim是一个在命令行界面下运行的文本编…...

如何优化垃圾回收机制?
垃圾回收机制 掌握 GC 算法之前,我们需要先弄清楚 3 个问题。第一,回收发生在哪里?第二,对象在 什么时候可以被回收?第三,如何回收这些对象? 回收发生在哪里? JVM 的内存区域中&…...
beyond the ‘PHYSICAL‘ memory limit.问题处理
Container [pid5616,containerIDcontainer_e50_1734408743176_3027740_01_000006] is running 507887616B beyond the ‘PHYSICAL’ memory limit. Current usage: 4.5 GB of 4 GB physical memory used; 6.6 GB of 8.4 GB virtual memory used. Killing container. 1.增大map…...
Day36【AI思考】-表达式知识体系总览
文章目录 **表达式知识体系总览**回答1:**表达式知识体系****一、三种表达式形式对比****二、表达式转换核心方法****1. 中缀转后缀(重点)****2. 中缀转前缀** **三、表达式计算方法****1. 后缀表达式计算(栈实现)****…...
段错误(Segmentation Fault)调试
1. 使用 GDB(GNU Debugger) GDB 是一个强大的调试工具,可以帮助你逐步执行程序并检查变量状态。 编译时添加调试信息: gcc -g your_program.c -o your_program启动 GDB: gdb ./your_program运行程序: …...

每日Attention学习19——Convolutional Multi-Focal Attention
每日Attention学习19——Convolutional Multi-Focal Attention 模块出处 [ICLR 25 Submission] [link] UltraLightUNet: Rethinking U-shaped Network with Multi-kernel Lightweight Convolutions for Medical Image Segmentation 模块名称 Convolutional Multi-Focal Atte…...
LeetCode题练习与总结:三个数的最大乘积--628
一、题目描述 给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。 示例 1: 输入:nums [1,2,3] 输出:6示例 2: 输入:nums [1,2,3,4] 输出:24示例 3&a…...

Colorful/七彩虹 隐星P15 TA 24 原厂Win11 家庭版系统 带F9 Colorful一键恢复功能
Colorful/七彩虹 隐星P15 TA 24 原厂Win11 家庭中文版系统 带F9 Colorful一键恢复功能 自动重建COLORFUL RECOVERY功能 带所有随机软件和机型专用驱动 支持机型:隐星P15 TA 24 文件下载:asusoem.cn/745.html 文件格式:ISO 系统版本&…...
第二篇:多模态技术突破——DeepSeek如何重构AI的感知与认知边界
——从跨模态对齐到因果推理的工程化实践 在AI技术从单一模态向多模态跃迁的关键阶段,DeepSeek通过自研的多模态融合框架,在视觉-语言-语音的联合理解与生成领域实现系统性突破。本文将从技术实现层面,解构其跨模态表征学习、动态融合机制与…...
CTreeCtrl 设置图标
mfc界面修改真难受 使用CTreeCtrl 进行设置导航视图时,有时候需要设置图标,一般使用如下代码 m_TreeViewImages.DeleteImageList();UINT uiBmpId IDB_ICONLIST_TREE;CBitmap bmp; if (!bmp.LoadBitmap(uiBmpId)) return;BITMAP bmpObj; bmp.GetBitmap…...
在JAX-RS中获取请求头信息的方法
在JAX-RS中获取请求头信息的方法 HeaderParam注解,可以直接将请求头中的特定值注入到方法参数中,代码示例: import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.core.Response;Path(&q…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...