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

C进程与Python子进程双向通信问题(基于双FIFO实现)

排查C→Python方向FIFO通信失效的常见坑点

老哥,你这个C+Python跨进程双向通信加日志的场景,我之前也踩过不少坑,尤其是FIFO方向失效的问题,大概率是在FIFO打开时机、子进程重定向、或者阻塞行为这几个地方出了问题,咱们一个个捋:

1. FIFO的打开顺序绝对是重灾区

有名管道(FIFO)的核心特性是:必须一端先打开读,另一端才能成功打开写(反之亦然),否则会一直阻塞在open()调用上。比如你如果在C进程里先创建FIFO,然后直接打开写端,这时候Python子进程还没启动,C就会卡在open()那里,根本没法继续启动子进程,自然没法通信。

解决办法:

  • 先创建两个FIFO,然后立刻fork()子进程
  • 子进程(Python端)先打开对应的读/写FIFO,再执行Python脚本
  • 父进程(C端)fork后,等待子进程完成FIFO打开操作(可以加个短sleep(1),生产环境用信号/文件锁更可靠),再打开自己的写/读FIFO

2. 子进程的stdin/stdout重定向别搞反

你要C往Python发数据,Python必须从C→P的FIFO读取对吧?那你在启动Python子进程时,有没有把它的stdin重定向到这个FIFO?如果没做重定向,Python默认读键盘输入,自然收不到C发的数据。

另外你要单独捕获Python的stdout做日志,这时候得用pipe管道来实现,不能和FIFO混在一起,否则会干扰双向通信的逻辑。

示例代码片段

C端核心逻辑

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

#define FIFO_C_TO_P "c_to_p.fifo"
#define FIFO_P_TO_C "p_to_c.fifo"

int main() {
    // 创建FIFO,设置全读写权限
    if (mkfifo(FIFO_C_TO_P, 0666) == -1 || mkfifo(FIFO_P_TO_C, 0666) == -1) {
        perror("mkfifo failed");
        exit(1);
    }

    // 创建pipe用于捕获Python的stdout
    int stdout_pipe[2];
    if (pipe(stdout_pipe) == -1) {
        perror("pipe failed");
        exit(1);
    }

    pid_t pid = fork();
    if (pid == 0) {
        // 子进程:配置Python的输入输出
        close(stdout_pipe[0]); // 关闭pipe读端
        dup2(stdout_pipe[1], STDOUT_FILENO); // 重定向stdout到pipe写端
        close(stdout_pipe[1]);

        // 重定向stdin到C→P的FIFO
        int c_to_p_fd = open(FIFO_C_TO_P, O_RDONLY);
        if (c_to_p_fd == -1) {
            perror("open c_to_p fifo failed");
            exit(1);
        }
        dup2(c_to_p_fd, STDIN_FILENO);
        close(c_to_p_fd);

        // 启动Python脚本
        execlp("python3", "python3", "py_script.py", NULL);
        perror("execlp failed");
        exit(1);
    } else {
        // 父进程:处理日志读取和FIFO写操作
        close(stdout_pipe[1]); // 关闭pipe写端

        // 读取Python的stdout日志
        char log_buf[256];
        ssize_t n;
        printf("Capturing Python stdout:\n");
        while ((n = read(stdout_pipe[0], log_buf, sizeof(log_buf)-1)) > 0) {
            log_buf[n] = '\0';
            printf("[LOG] %s", log_buf);
        }
        close(stdout_pipe[0]);

        // 等待子进程打开FIFO后,写入测试数据
        sleep(1);
        int c_to_p_fd = open(FIFO_C_TO_P, O_WRONLY);
        if (c_to_p_fd == -1) {
            perror("open c_to_p fifo failed");
            exit(1);
        }
        const char* msg = "Hello from C process!";
        write(c_to_p_fd, msg, strlen(msg));
        close(c_to_p_fd);

        // 等待子进程退出,清理FIFO
        wait(NULL);
        unlink(FIFO_C_TO_P);
        unlink(FIFO_P_TO_C);
    }
    return 0;
}

Python端脚本(py_script.py)

import sys

# 读取C进程发来的数据(stdin已重定向到FIFO)
data = sys.stdin.read()
print(f"Python received: {data}")

# 可选:往P→C的FIFO回发数据
# with open("p_to_c.fifo", "w") as f:
#     f.write("Hello from Python!")

3. FIFO的权限设置别偷懒

创建FIFO时一定要设置足够的权限,比如mkfifo("c_to_p.fifo", 0666),不然Python进程可能因为权限不足无法打开FIFO,直接静默退出,你还找不到原因。

4. Python的读取逻辑要匹配C的写入方式

如果Python用input()或sys.stdin.readline()读取,但C发送的数据没有换行符,Python会一直等待换行,看起来就像没收到数据。可以:

  • C发送时末尾加换行符
  • Python用sys.stdin.read()读取(直到FIFO被关闭)
  • 双方约定固定长度的字节,Python循环读取指定长度

如果还是不行,可以把你的实际代码片段贴出来,我帮你再细查~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:16:18