双向管道通信读取端出现Bad file descriptor错误排查
客户端-服务器双向管道通信问题解决
错误根源分析
- 管道写端未及时关闭导致read阻塞:父进程(服务器)在读取p2管道前,未关闭自身持有的p2[1](写端)。子进程写完关闭p2[1]后,管道写端仍有父进程的一个打开实例,
read(p2[0], ...)会一直等待数据,陷入死循环。 - 进程等待时机错误:父进程先调用
wait(NULL)等待子进程退出,再读取管道数据,可能导致管道资源提前回收,同时未关闭的写端依然会引发阻塞。 - 错误提示信息混淆:子进程写管道失败时,错误提示写成了"Can't read from the pipe!",与实际操作不符。
修复后的代码调整
父进程(服务器)代码调整
if (pid != 0) // server { read(fd_client_to_server, word1, sizeof(word1)); // 读取客户端发送的命令 printf(" I received this command...%s\n", word1); if (strcmp(word1, "read login : username") == 0 || strcmp(word1, "quit") == 0 || strcmp(word1, "logout") == 0 || strcmp("get-logged-users", word1) == 0 || strcmp("get-proc-info", word1) == 0) { // 父进程仅向p1写数据,关闭p1读端 close(p1[0]); if (write(p1[1], word1, sizeof(word1)) == -1) perror("Can't write in the pipe\n"); printf(" 2 I received this command...%s\n", word1); close(p1[1]); // 父进程仅从p2读数据,提前关闭p2写端,避免read阻塞 close(p2[1]); // 先读取子进程返回的数据,再等待子进程退出 if (read(p2[0], word2, sizeof(word2)) == -1) perror("Can't read from pipe\n"); printf("4 I received this command...%s\n", word2); close(p2[0]); wait(NULL); // 等待子进程退出 write(fd_server_to_client, word2, sizeof(word2)); // 将数据转发给客户端 } else { printf("%s\n", "The server can't do this yet!"); } }
子进程(CP)代码调整
else { // CP close(p1[1]); if (read(p1[0], word3, sizeof(word3)) == -1) { perror("Can't read from the pipe!"); } printf(" 2 I received this command...%s\n", word3); close(p1[0]); if (strcmp(word3, "quit") == 0) strcpy(word4, "yay!"); close(p2[0]); if (write(p2[1], word4, sizeof(word4)) == -1) { perror("Can't write to the pipe!"); // 修正错误提示信息 } printf(" 3 I received this command...%s\n", word4); close(p2[1]); }
额外注意事项
- 管道必须在
fork()前调用pipe(p1)和pipe(p2)创建,确保父子进程继承正确的文件描述符。 - 所有管道的未使用端需及时关闭,避免资源泄漏和不必要的阻塞。
- 注意客户端发送命令可能携带的换行符,可使用
strncmp或提前去除换行后再做字符串比较,避免匹配失败。
内容的提问来源于stack exchange,提问作者andreea_0607
相关产品推荐
相关产品推荐

