我有两个进程(“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");
}
}
最佳答案
基本上,您不应该在运行ls
之前等待grep
死亡。ls
命令可能生成的数据太多,无法全部存储在管道中,因此ls
命令将阻塞,直到另一个进程从管道中读取数据,但另一个进程正在等待ls
完成,然后再尝试从管道中读取任何数据。这是个僵局。
另外,通过这样的等待,您可以强制执行串行执行,这会丢掉多个内核的好处。
你应该做一些小的改进。报告错误的点有很多。应在标准错误流(stderr
上报告错误,而不是在stdout
上报告错误。您还应该确保程序在至少出现某些错误后不会继续。
您不必测试任何exec*()
系统调用的返回值。如果函数返回,则失败。再一次,您应该确保进程在这之后退出。在这个程序中,孩子继续下去并不重要;在许多程序中,不退出会导致混乱(例如,同时读取标准输入的两个进程)。
不需要将pipe_fd
作为全局变量。请确保您的所有邮件都以换行符结尾。您没有包含<sys/wait.h>
所以您在waitpid()
函数的作用域中没有原型——这通常是个坏主意。您应该将编译器设置为fussy,以便它要求在使用或定义每个函数之前,其作用域中都有一个原型。可以在定义中初始化参数列表:
char *prog1_argv[] = { "ls", "-l", "/", NULL };
char *prog2_argv[] = { "grep", "s", NULL };
这有一个至关重要的有益的副作用,即不使用空指针(如hisMatthias中的answer所述)。我还删除了数组的大小;第二个数组的维数是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);
}
关于c - 无法写入2个进程的管道IPC,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19095173/