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
相关产品推荐
相关产品推荐

