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

使用poll()结合POLLIN等待文件变化时触发无限循环的问题

解决poll()监听sysfs文件时POLLIN无限触发的问题

问题原因

  • 普通文件的poll行为:普通文件的poll()实现会始终返回POLLIN,因为系统认为普通文件随时可读取(无论内容是否变化),所以用普通文件测试内核通知场景本身不适用。
  • sysfs文件读取不彻底:你的代码仅调用一次read(),若未读到EOF(比如缓冲区buf小于属性内容,或未消费完所有数据),poll()会判定仍有数据可读,从而持续触发POLLIN。

修复方案

针对sysfs文件的正确处理方式:

  1. 读取到EOF:每次poll()触发POLLIN后,循环调用read()直到返回0(EOF),确保彻底读取当前属性内容,这样下次poll()才会等待内核sysfs_notify()的通知。
  2. 适配sysfs特性:sysfs属性更新会通过sysfs_notify()唤醒等待的poll(),但只有读完所有当前内容后,才会进入等待状态。

修改后的代码示例:

...
struct pollfd *fds = malloc(sizeof(struct pollfd) * 1);
char buf[256];
ssize_t ret;

fds[0].fd = open("/path/to/sysfs-file", O_RDONLY);
if (fds[0].fd < 0) {
    free(fds);
    return -EXIT_FAILURE;
}
fds[0].events = POLLIN;
fds[0].revents = 0;

while (poll(fds, 1, -1) > 0) {
    if (fds[0].revents & POLLIN) {
        fds[0].revents = 0;
        // 循环读取直到EOF,确保清空所有可读数据
        while ((ret = read(fds[0].fd, buf, sizeof(buf))) > 0) {
            // 处理读取到的数据,如打印或解析
            // printf("Read: %.*s", (int)ret, buf);
        }
        // 处理read错误(排除中断信号)
        if (ret == -1 && errno != EINTR) {
            perror("read failed");
            break;
        }
    }
}

close(fds[0].fd);
free(fds);
...

额外说明

  • 不要用普通文件测试sysfs的poll()通知逻辑,普通文件不支持内核主动触发的通知机制,poll()持续返回POLLIN是预期行为。
  • 部分sysfs属性会使用POLLPRI事件,可尝试监听POLLIN | POLLPRI,读取后用lseek(fd, 0, SEEK_SET)重置文件指针,但大部分场景下,读取到EOF即可解决问题。

内容的提问来源于stack exchange,提问作者Anton Kalistratov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 01:27:42