[英]Unable to write into pipe IPC for 2 processes
我有2个进程('ls'进程和'grep')。 我正在使用管道在两者之间进行通信。 但是grep进程无法从管道中读取。 你能帮我搞清楚为什么会这样吗?
这是我的代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int pipe_fd[2];
int main()
{
pid_t p1,p2;
char *prog1_argv[4];
char *prog2_argv[2];
/* Build argument list */
prog1_argv[0] = "ls";
prog1_argv[1] = "-l";
prog1_argv[2] = "/";
prog1_argv[3] = NULL;
prog2_argv[0] = "grep";
prog2_argv[1] = "s";
prog2_argv[1] = NULL;
if (pipe(pipe_fd) < 0)
{
printf ("pipe failed");
}
p1 = fork();
if(p1 == 0)
{
printf("in child\n");
close(pipe_fd[0]);
if(dup2(pipe_fd[1],1)<0)
{
printf("dup failed:%d\n",errno);
}
close(pipe_fd[1]);
if(execvp (prog1_argv[0], prog1_argv)<0)
printf("exec failed");
}
if(p1>0)
{
printf("im in parent\n");
waitpid(p1,NULL,0);
printf("parent: child exited. Now test the pipe\n");
close(pipe_fd[1]);
if(dup2(pipe_fd[0],0)<0)
{
printf("dup failed:%d\n",errno);
}
close(pipe_fd[0]);
if(execvp (prog2_argv[0], prog2_argv)<0)
printf("exec failed");
}
}
你重写你的grep的参数。 尝试:
int main()
{
pid_t p1,p2;
char *prog1_argv[4];
char *prog2_argv[3];
/* Build argument list */
prog1_argv[0] = "ls";
prog1_argv[1] = "-l";
prog1_argv[2] = "/";
prog1_argv[3] = NULL;
prog2_argv[0] = "grep";
prog2_argv[1] = "s";
prog2_argv[2] = NULL;
// ...
从根本上说,在运行grep
之前,你不应该等待ls
死掉。
ls
命令可能会生成如此多的数据,以至于它不能全部存储在管道中,因此ls
命令将阻塞,直到另一个进程从管道读取,但另一个进程在尝试读取之前等待ls
完成管道里的任何东西。 这是一个僵局。
此外,通过这样等待,您可以强制执行串行执行,从而避免了多个内核的优势。
你应该做一些小的改进。 报告错误有多种方面。 错误应该在标准错误流( stderr
)上报告,而不是在stdout
。 您还应该确保在至少一些错误之后程序不会继续。
您不必测试任何exec*()
系统调用的返回值。 如果函数返回,则失败。 而且,您应该确保在此之后退出流程。 在这个计划中,孩子继续并不重要; 在许多程序中,不退出会导致混乱(例如,两个进程试图同时读取标准输入)。
pipe_fd
不需要是全局变量。 请确保您的所有邮件以换行符结尾。 你没有包含<sys/wait.h>
所以你没有在waitpid()
函数的范围内使用原型 - 这通常是一个坏主意。 您应该将编译器设置为繁琐,因此它要求每个函数在使用或定义之前都在范围内具有原型。 您可以在定义中初始化参数列表:
char *prog1_argv[] = { "ls", "-l", "/", NULL };
char *prog2_argv[] = { "grep", "s", NULL };
这有一个至关重要的有益副作用,即没有使用NULL指针切换prog_argv2[1]
(正如Matthias在他的回答中所述 。我也删除了数组的大小;第二个的大小为2,需要为3,但是当你这样初始化时,编译器会进行计数。
你正确做的一件事是正确的做法是确保管道文件描述符全部关闭。
这适合我:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(void)
{
pid_t p1;
int pipe_fd[2];
char *prog1_argv[] = { "ls", "-l", "/", NULL };
char *prog2_argv[] = { "grep", "s", 0 };
if (pipe(pipe_fd) < 0)
{
fprintf(stderr, "pipe failed:%d\n", errno);
exit(1);
}
p1 = fork();
if (p1 == 0)
{
printf("In child\n");
close(pipe_fd[0]);
if (dup2(pipe_fd[1], 1) < 0)
{
fprintf(stderr, "dup failed:%d\n", errno);
exit(1);
}
close(pipe_fd[1]);
execvp(prog1_argv[0], prog1_argv);
fprintf(stderr, "exec failed:%d\n", errno);
exit(1);
}
if (p1 > 0)
{
printf("In parent\n");
close(pipe_fd[1]);
if (dup2(pipe_fd[0], 0) < 0)
{
fprintf(stderr, "dup failed:%d\n", errno);
exit(1);
}
close(pipe_fd[0]);
execvp(prog2_argv[0], prog2_argv);
fprintf(stderr, "exec failed:%d\n", errno);
exit(1);
}
fprintf(stderr, "Fork failed:%d\n", errno);
return(1);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.