Unix管道父子进程双向通信报错:参数过少问题求助
父子进程管道双向通信的参数过少错误解决
我正在编写Unix环境下的程序,实现父子进程通过pipe双向收发消息。现有代码可实现父进程写、子进程读的单向通信,但修改为双向通信后,子进程写入消息时始终出现"too few arguments"(参数过少)错误。
我将父进程写消息的逻辑复制到子进程中,逻辑为:关闭pipe的READ_END(读端),传入变量写入消息,关闭WRITE_END(写端),读取pipe内消息并传递给读函数,关闭读端后打印内容。但该逻辑在子进程中报错。
我尝试过添加子进程专属消息、复用读函数等方式,均未解决参数过少的问题。父进程与子进程传入参数仅消息内容不同,父进程可正常运行,子进程却报错。以下是我的代码:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <wait.h> #define BUFFER_SIZE 40 #define READ_END 0 #define WRITE_END 1 int main(void) { char write_msg[BUFFER_SIZE] = "People all over the world, join hands!"; char write_msg2[BUFFER_SIZE] = "Start a Love Train (Love Train)!"; char read_msg[BUFFER_SIZE]; pid_t pid; int fd[2]; if (pipe(fd) == -1) { fprintf(stderr,"Pipe failed"); return 1; } pid = fork(); if (pid < 0) { fprintf(stderr, "Fork failed"); return 1; } if (pid > 0) { close(fd[READ_END]); write(fd[WRITE_END], write_msg, strlen(write_msg)+1); close(fd[WRITE_END]); read(fd[READ_END], read_msg, BUFFER_SIZE); close(fd[READ_END]); printf("parent: %s\n",read_msg); wait(NULL); } else { close(fd[READ_END]); write(fd[WRITE_END], write_msg2, strlen(write_msg2)+1); close(fd[WRITE_END]); read(fd[READ_END], read_msg, BUFFER_SIZE); close(fd[READ_END]); printf("child: %s\n",read_msg); } return 0; }
错误原因分析
- 管道半双工特性限制:单个管道只能实现单向数据传输,无法同时完成双向通信,你试图用同一个管道既发送又接收,导致文件描述符操作逻辑混乱。
- 无效文件描述符调用:父进程和子进程都先关闭了管道的读端(
fd[READ_END]),之后又尝试调用read(fd[READ_END], ...),此时该文件描述符已被关闭,属于非法引用,这会触发系统调用错误,表现为你看到的"参数过少"提示(实际是文件描述符非法导致的调用异常)。
修正后的代码
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <wait.h> #define BUFFER_SIZE 40 #define READ_END 0 #define WRITE_END 1 int main(void) { char parent_msg[BUFFER_SIZE] = "People all over the world, join hands!"; char child_msg[BUFFER_SIZE] = "Start a Love Train (Love Train)!"; char read_buf[BUFFER_SIZE]; pid_t pid; // 两个管道:fd1用于父写子读,fd2用于子写父读 int fd1[2], fd2[2]; // 创建第一个管道 if (pipe(fd1) == -1) { fprintf(stderr, "Pipe 1 failed\n"); return 1; } // 创建第二个管道 if (pipe(fd2) == -1) { fprintf(stderr, "Pipe 2 failed\n"); return 1; } pid = fork(); if (pid < 0) { fprintf(stderr, "Fork failed\n"); return 1; } if (pid > 0) { // 父进程逻辑 // 关闭不需要的管道端:fd1读端(父只写)、fd2写端(父只读) close(fd1[READ_END]); close(fd2[WRITE_END]); // 向子进程发送消息 write(fd1[WRITE_END], parent_msg, strlen(parent_msg) + 1); close(fd1[WRITE_END]); // 写完关闭写端 // 读取子进程的消息 read(fd2[READ_END], read_buf, BUFFER_SIZE); printf("parent received: %s\n", read_buf); close(fd2[READ_END]); wait(NULL); } else { // 子进程逻辑 // 关闭不需要的管道端:fd1写端(子只读)、fd2读端(子只写) close(fd1[WRITE_END]); close(fd2[READ_END]); // 读取父进程的消息 read(fd1[READ_END], read_buf, BUFFER_SIZE); printf("child received: %s\n", read_buf); close(fd1[READ_END]); // 向父进程发送消息 write(fd2[WRITE_END], child_msg, strlen(child_msg) + 1); close(fd2[WRITE_END]); } return 0; }
关键修改说明
- 双管道实现双向通信:创建
fd1和fd2两个管道,分别负责不同方向的数据传输,规避单管道半双工的限制。 - 精准管理文件描述符:每个进程仅保留自己需要使用的管道端,关闭多余的端,避免资源泄漏和非法调用。
- 调整通信顺序:父进程先发送再接收,子进程先接收再发送,确保通信逻辑顺畅,避免死锁。
内容的提问来源于stack exchange,提问作者Christian Rocha
相关产品推荐
相关产品推荐

