You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

fgets()读取/sys/bus/temp1_input时阻塞卡死,求助排查原因

问题分析与解决方案

你的问题核心是**/sys虚拟文件系统的特殊性**导致的fgets阻塞,而非单纯的文件开关操作。以下是具体原因和解决办法:

可能的原因

  1. /sys文件的内核驱动逻辑:/sys下的文件并非磁盘真实文件,每次读取都会触发内核驱动去采集传感器数据。如果传感器驱动在多次读取后出现资源锁、死循环或响应滞后,就会导致用户态的fgets因等待内核返回数据而卡住。而cat命令的读取逻辑(比如一次性读取整个文件、不同的系统调用组合)可能绕过了驱动的异常状态,或者内核在处理cat的请求时重新恢复了响应。
  2. stdio缓冲的干扰:fgets属于stdio库函数,自带用户态缓冲。当与/sys这类动态生成内容的虚拟文件交互时,缓冲机制可能导致数据同步异常,进而引发阻塞。

解决办法

1. 改用系统调用直接读取(绕过stdio缓冲)

替换fopen/fgets为open/read/close,避免stdio的缓冲逻辑干扰:

// 替换原代码的读取逻辑
int fd = open("/sys/bus/temp1_input", O_RDONLY);
if (fd != -1) {
    char val_str[10];
    // 读取数据,预留空间给结束符
    ssize_t bytes_read = read(fd, val_str, sizeof(val_str) - 1);
    if (bytes_read > 0) {
        val_str[bytes_read] = '\0'; // 手动添加字符串结束符
        temp_val = atoi(val_str);
    }
    close(fd);
}

2. 保持文件句柄长期打开,避免频繁开关

/sys文件打开后,每次读取都会重新触发数据采集,无需反复关闭再打开。长期持有句柄可以减少驱动层面的资源申请/释放操作,降低异常概率:

// 程序初始化阶段打开一次文件
int fd = open("/sys/bus/temp1_input", O_RDONLY);
if (fd == -1) {
    // 处理打开失败的逻辑,比如打印错误
    perror("open temp1_input failed");
}

// 每次扫描时的操作
if (fd != -1) {
    // 移动文件指针到开头
    lseek(fd, 0, SEEK_SET);
    char val_str[10];
    ssize_t bytes_read = read(fd, val_str, sizeof(val_str) - 1);
    if (bytes_read > 0) {
        val_str[bytes_read] = '\0';
        temp_val = atoi(val_str);
    }
}

// 程序退出前关闭文件
if (fd != -1) {
    close(fd);
}

3. 排查内核驱动状态

如果上述方法仍无效,通过dmesg命令查看内核日志,检查是否有温度传感器驱动的错误信息(比如资源死锁、硬件异常),这可能需要驱动层面的修复。

关于非阻塞模式的说明

给open添加O_NONBLOCK标志可以让read不会阻塞,但这只是避免程序卡住,无法解决驱动层面的异常。此时read会返回-1并设置errno为EAGAIN,你需要处理这种情况并考虑重试策略,但这并非根本解决方案。

内容的提问来源于stack exchange,提问作者Easha Jilakar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:53:04