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

Linux 命名管道FIFO读写到文件描述符1023时停止运行问题咨询

故障原因分析
  • 核心根因:读端文件描述符泄漏
    读端代码在死循环内每次都调用open()打开命名管道,但是读取完数据后从未调用close()关闭本次申请的文件描述符,每轮循环都会泄漏一个文件描述符。Linux系统默认单进程允许打开的最大文件描述符数量为1024,0、1、2分别被标准输入、标准输出、标准错误占用,因此新分配的文件描述符从3开始递增,到1023时已经达到进程上限,后续open()调用直接返回-1,读端不再执行数据读取和日志打印逻辑。
  • 写端同步停止的原因
    命名管道在内核中配有固定大小的缓冲区,当读端停止读取数据后,缓冲区很快被写端持续写入的数据占满,此时写端执行write()系统调用会陷入阻塞,无法继续执行后续的日志打印和sleep逻辑,表现为和读端同步停止。
修复方案

方案1:最简修复,解决泄漏问题

在读端的每次循环结束前关闭本次打开的文件描述符即可,修改后读端核心逻辑如下:

while(1) {
    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);

    if (fd != -1) {
        if (read(fd, buf, sizeof(buf)) > 0) {
            printf("fd: %d. Received buffer: %s\n", fd, buf);
        }
        // 新增关闭逻辑,避免文件描述符泄漏
        close(fd);
    }
    sleep(0.2);
}

方案2:性能优化,避免频繁打开关闭管道

命名管道不需要每次读取都重新打开,读端也可以和写端一样只打开一次,循环读取即可,开销更低,修改后读端完整代码如下:

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#define MAX_BUF 500

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[MAX_BUF];

    // 提前打开一次管道即可
    fd = open(myfifo, O_RDONLY);
    if (fd == -1) {
        perror("open fifo failed");
        return 1;
    }

    while(1) {
        if (read(fd, buf, sizeof(buf)) > 0) {
            printf("Received buffer: %s\n", buf);
        }
        sleep(0.2);
    }
    close(fd);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:06:00