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

如何无阻塞地以只写方式打开FIFO(命名管道)?

解决FIFO只写打开阻塞且非阻塞模式报错的问题

FIFO的默认机制是:仅以O_WRONLY打开时会阻塞,直到有进程以只读方式打开该管道;而添加O_NONBLOCK标志后,若此时无只读进程,open会直接返回ENXIO错误。你遇到的正是这个矛盾场景,以下是符合你“先只写打开再fork”要求的解决方案:

核心思路

先以O_WRONLY | O_NONBLOCK尝试打开FIFO,即便因无读者返回ENXIO错误,也不终止进程,继续执行fork创建子进程。待子进程打开只读FIFO后,父进程再重新以阻塞模式打开只写FIFO,此时因已有读者存在,不会再阻塞。

修改后的代码

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    // 先尝试非阻塞只写打开,仅在非ENXIO错误时退出
    int pipe_fd = open("/tmp/ngfifo", O_WRONLY | O_NONBLOCK);
    if (pipe_fd < 0) {
        if (errno != ENXIO) {
            fprintf(stderr, "Opened fifo failed %d\n", errno);
            return -1;
        }
        printf("No reader yet, proceed to fork\n");
    } else {
        close(pipe_fd); // 意外打开成功则先关闭,后续重新打开
    }

    pid_t pid = fork();
    if (pid > 0) {
        // 父进程等待子进程完成只读打开(生产环境建议用信号/管道同步)
        usleep(1000);
        // 重新以阻塞模式打开只写FIFO
        pipe_fd = open("/tmp/ngfifo", O_WRONLY);
        if (pipe_fd < 0) {
            fprintf(stderr, "Reopen fifo failed %d\n", errno);
            wait(NULL);
            return -1;
        }
        printf("begin to write \n");
        // 此处添加写操作逻辑
        close(pipe_fd);
        wait(NULL);
    } else if (pid == 0) {
        // 子进程打开只读FIFO
        int read_fd = open("/tmp/ngfifo", O_RDONLY);
        if (read_fd < 0) {
            fprintf(stderr, "Open read fifo failed %d\n", errno);
            return -1;
        }
        printf("begin to read \n");
        // 此处添加读操作逻辑
        close(read_fd);
    } else {
        fprintf(stderr, "Fork failed %d\n", errno);
        return -1;
    }
    return 0;
}

注意事项

  • 代码中用usleep做简单同步,生产环境建议用信号、匿名管道等更可靠的同步方式,避免父进程在子进程打开FIFO前就重新尝试打开。
  • 确保FIFO已通过mkfifo /tmp/ngfifo命令创建,且权限正确(如mkfifo -m 0666 /tmp/ngfifo避免权限问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 16:05:31