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…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...