一、sysfs 属性的调试用途
- 在线动态调试参数
- 实时调整驱动变量(如波特率、模式、策略、阈值等)
- 不需重启设备或重载驱动
- 状态监控
- 导出硬件/驱动内部状态的只读属性:温度/电池电量/寄存器值/内部统计等
- 利于远程采集和监控硬件健康
- 辅助定位与故障排查
- 允许临时打开详细 log,或导出底层寄存器信息
- 支持查看"最近一次错误码"、调试开关等
- 控制行为/功能切换
- 通过简单 echo 即可临时修改行为配置,如切换工作模式、重置统计、强制上电/下电等
二、典型操作实例
我们将结合上一章节的 10_touch_sysfs_file/ 的源码进行讲解。
1. 查看属性
查看值
bash
cat /sys/class/class_test/device_test/myparam
# 输出:421
2
2
2. 配置参数
写入新值
bash
# 写入88
echo 88 | sudo tee /sys/class/class_test/device_test/myparam
cat /sys/class/class_test/device_test/myparam
# 输出:881
2
3
4
5
2
3
4
5
3. 开启/关闭调试功能的典型属性
假如我们在驱动里设计了开关:
c
static int debug_enable = 0; // 调试开关
// 读操作时调用
static ssize_t debug_show(struct device *dev, struct device_attribute *attr, char *buf)
{
// 将 debug_enable 的值格式化为字符串,写入 buf 缓冲区
return sprintf(buf, "%d\n", debug_enable);
}
// 写操作时调用
static ssize_t debug_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int val;
// kstrtoint 是内核帮助函数:用于将字符串(如 "88\n", "123", "007", 等等)解析为整型数值。
if (kstrtoint(buf, 10, &val) == 0) {
// 成功解析,更新 debug_enable 的值
debug_enable = !!val; // 将非零值转换为 1,零值保持为 0
printk(KERN_INFO "mychardev: debug_enable set to %d\n", debug_enable); // 打印新值到内核日志
}
// 返回写入的字节数
return count;
}
DEVICE_ATTR_RW(debug); // 创建可读写的设备属性 debug
// ...init里 device_create_file(dev, &dev_attr_debug);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
debug_enable = !!val;相当于:cif (val) debug_enable = 1; else debug_enable = 0;1
2
3
4
说明
!val:- 逻辑非,val 为0时结果为1,val非0时结果为0。
!!val:- 再取一次非。
- 把任何“非零”数变为 1,把 0 变为 0。
| val | !val | !!val | 赋值后 debug_enable |
|---|---|---|---|
| 0 | 1 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| -3 | 0 | 1 | 1 |
| 99 | 0 | 1 | 1 |
清洗或规范布尔变量的值,避免 val 为除0/1之外的数字(比如2、-4、123)时,
debug_enable不是干净的0或1。保证开关变量只有0或1。
调试时用:
bash
# 打开调试
echo 1 | sudo tee /sys/class/class_test/device_test/debug
# 关闭调试
echo 0 | sudo tee /sys/class/class_test/device_test/debug1
2
3
4
5
2
3
4
5
4. 查询多种状态或配置
对于输出结构化信息常见用法:
c
static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE,
"param=%d\nerror=%d\nstatus=%s\n", myparam, last_error, state_str);
}
DEVICE_ATTR_RO(status);1
2
3
4
5
6
2
3
4
5
6
三、规范及建议
1. 命名简洁直观
属性建议全小写、不要有空格,意义明确如 enable, mode, threshold, debug。
2. 权限配置
RO(只读):如状态、统计,只用showRW(读写):如参数、可配置项,show/store都要写WO(只写,少见):如敏感操控(比如触发一次复位)
3. 错误与输入检查
- store 回调必须校验输入,避免写入非法值导致混乱
- 如赋值范围、格式检查,必要时返回
-EINVAL
4. 同步与安全
- 回调里如涉及全局变量、硬件操作,要注意加锁避免并发访问问题
5. 返回值说明
- show 返回实际写入 buf 字节数
- store 返回 count(成功处理了多少字节),否则写操作可能异常/不完整