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

Python与C程序通过pipe通信出现Bad file descriptor错误排查

管道通信问题:Python父进程与C子进程通信失败排查

尝试用pipe()实现Python程序与C程序间的字符串交换,失败并报错;但两个C程序间用pipe()通信完全正常。

Python父进程代码

import os


def main():
    r, w = os.pipe()
    pid = os.fork()

    if pid == 0:
        os.close(r)
        print('fd =', w)
        name = '/home/subado/tmp/pipes/c'  # compiled c.c
        os.execl(name, name, str(w))
    else:
        os.close(w)
        os.waitpid(-1, 0)
        print('Parent receive: ', os.read(r, 10))
        os.close(r)


if __name__ == "__main__":
    main()

C子进程代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  if (argc < 2) {
    exit(EXIT_FAILURE);
  }
  char buf[] = "1000 - 7?";
  int fd = (int)strtol(argv[1], (char **)NULL, 10);
  printf("fd = %d\n", fd);
  ssize_t count = write(fd, buf, sizeof(buf));
  if (count == -1) {
    perror("write");
    exit(EXIT_FAILURE);
  } else {
    printf("Child send: %s\n", buf);
  }
  close(fd);
  exit(EXIT_SUCCESS);
}

Python父程序运行输出

fd = 4
fd = 4
write: Bad file descriptor
Parent receive:  b''

C父进程代码(通信正常)

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void) {
  int pipefd[2];

  if (pipe(pipefd) == -1) {
    perror("pipe");
    exit(EXIT_FAILURE);
  }
  pid_t cpid = fork();
  if (cpid == -1) {
    perror("fork");
    exit(EXIT_FAILURE);
  }

  if (cpid == 0) {
    close(pipefd[0]);
    printf("fd = %d\n", pipefd[1]);
    const char *child = "/home/subado/tmp/pipes/c"; // compiled c.c
    const int ENOUGH = (int)((ceil(log10(pipefd[1])) + 1) * sizeof(char));
    char str[ENOUGH];
    sprintf(str, "%d", pipefd[1]);

    execl(child, child, str, NULL);
  } else {
    close(pipefd[1]);
    int statloc;
    waitpid(-1, &statloc, 0);
    char buf[10];
    read(pipefd[0], buf, sizeof(buf));
    printf("Parent receive: %s", buf);
    close(pipefd[0]);
  }
  return 0;
}

C父程序运行输出

fd = 4
fd = 4
Child send: 1000 - 7?
Parent receive: 1000 - 7?

问题

  • 为何会出现Bad file descriptor错误?
  • Python与C父程序的差异是什么?
  • 为何Python代码无法正常工作?

解决方案与原因

解决方案

在Python子进程分支的os.execl(name, name, str(w))语句前,添加一行代码:

os.set_inheritable(w, True)

原因

Python的os.pipe()返回的文件描述符默认不可继承,而C语言中pipe()创建的文件描述符默认是可继承的。当Python通过execl启动C子进程时,未设置可继承标记的文件描述符会被自动关闭,导致C子进程拿到的文件描述符是无效的,因此触发Bad file descriptor错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 15:33:10