[英]Trouble using dup2 to make a C program execute a command such as 'ls /bin | grep grep | grep b'
I'm having trouble using dup2 to make ac program execute a command such as ls /bin | grep grep | grep b
我在使用dup2使ac程序执行
ls /bin | grep grep | grep b
等命令时遇到问题 ls /bin | grep grep | grep b
ls /bin | grep grep | grep b
. ls /bin | grep grep | grep b
。 When I comment out the third command and associated pipe it executes ls /bin | grep grep
当我注释掉第三个命令和相关管道时,它执行
ls /bin | grep grep
ls /bin | grep grep
fine, but with the last command it just returns right away. ls /bin | grep grep
很好,但是使用最后一个命令,它会立即返回。 Also when I enter 'ps' the processes are still running. 同样,当我输入“ ps”时,进程仍在运行。 I think it's due to how I close the pipes.
我认为这是由于我如何关闭管道。 My code is below:
我的代码如下:
int main()
{
int pipeA[2];
int pipeB[2];
pipe(pipeA);
pipe(pipeB);
int pidA,pidB,pidC;
if(pidA = fork())
{
close(pipeA[0]);
dup2(pipeA[1],1);
close(pipeA[1]);
execlp("ls","ls","/bin",NULL);
printf("error\n");
}
if(pidB = fork())
{
close(pipeA[1]);
dup2(pipeA[0],0);
close(pipeA[0]);
close(pipeB[0]);
dup2(pipeB[1],1);
close(pipeB[1]);
execlp("grep","grep","grep",NULL);
printf("error\n");
}
if(pidC = fork())
{
close(pipeB[1]);
dup2(pipeB[0],0);
close(pipeB[0]);
execlp("grep","grep","b",NULL);
printf("error");
}
while(pidA != wait(0)){}
return 0;
}
You aren't closing enough file descriptors. 您没有关闭足够的文件描述符。
/* Semi-working code */
int main()
{
int pipeA[2];
int pipeB[2];
pipe(pipeA);
pipe(pipeB);
int pidA,pidB,pidC;
if (pidA = fork())
{
close(pipeB[0]); // "ls" is not going to use the second pipe
close(pipeB[1]); // Ditto
close(pipeA[0]);
dup2(pipeA[1], 1);
close(pipeA[1]);
execlp("ls", "ls", "/bin", (char *)NULL);
fprintf(stderr, "error executing 'ls'\n");
exit(1);
}
if (pidB = fork())
{
close(pipeA[1]);
dup2(pipeA[0],0);
close(pipeA[0]);
close(pipeB[0]);
dup2(pipeB[1],1);
close(pipeB[1]);
execlp("grep", "grep", "grep", (char *)NULL);
fprintf(stderr, "error execing 'grep grep'\n");
exit(1);
}
if (pidC = fork())
{
close(pipeA[0]); // The second grep is not going to use the first pipe
close(pipeA[1]); // Ditto
close(pipeB[1]);
dup2(pipeB[0],0);
close(pipeB[0]);
execlp("grep", "grep", "b", (char *)NULL);
fprintf(stderr, "error execing 'grep b'\n");
exit(1);
}
close(pipeA[0]); // The parent process is not using the pipes at all
close(pipeA[1]);
close(pipeB[0]);
close(pipeB[1]);
while (pidA != wait(0))
;
return 0;
}
Because you didn't close pipeA
in the second grep
, you end up with the first grep
waiting for input from the pipe the second grep
still has open, even though the process will not write to it. 因为您没有在第二个
grep
关闭pipeA
,所以最后一个第一个grep
等待来自第二个grep
仍然打开的管道的输入,即使该进程不会对其进行写入。 Because of that, the first grep
does not finish, so the second doesn't finish either - even though the ls
does complete. 因此,第一个
grep
不会完成,因此第二个grep
也不会完成-即使ls
已经完成。 These comments would apply even if the parent process closed its copies of the pipes - as the corrected code does. 即使父进程关闭了其管道副本,这些注释也将适用-就像更正后的代码一样。
Notice how you end up closing all 4 descriptors returned by the two calls to pipe()
in each of the four processes - three children and the parent process. 请注意,如何最终关闭四个进程中的每个进程(三个子进程和父进程
pipe()
的两次调用pipe()
返回的所有4个描述符。
This leaves one residual problem - the process hierarchy is upside down because of your aconventional use of if (pidA = fork())
. 这留下了一个残留的问题-由于您常规使用
if (pidA = fork())
因此流程层次结构颠倒了。 You have a child process waiting for its parents. 您有一个子进程正在等待其父进程。 You need to use:
您需要使用:
if ((pidA = fork()) == 0)
{
/* Be childish */
}
Similarly for each of the other two processes. 其他两个过程中的每个过程类似。 You should also check the
pipe()
calls and the fork()
calls for failure, just to be sure. 为了确保安全,您还应该检查
pipe()
调用和fork()
调用是否失败。
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/wait.h>
#include <stdlib.h>
static void err_exit(const char *format, ...);
/* Working code */
int main(void)
{
int pipeA[2];
int pipeB[2];
if (pipe(pipeA) != 0 || pipe(pipeB) != 0)
err_exit("Failed to create a pipe\n");
int pidA,pidB,pidC;
if ((pidA = fork()) < 0)
err_exit("Failed to fork (A)\n");
else if (pidA == 0)
{
close(pipeB[0]); // "ls" is not going to use the second pipe
close(pipeB[1]); // Ditto
close(pipeA[0]);
dup2(pipeA[1], 1);
close(pipeA[1]);
execlp("ls", "ls", "/bin", (char *)NULL);
err_exit("error executing 'ls'\n");
}
if ((pidB = fork()) < 0)
err_exit("failed to fork (B)\n");
else if (pidB == 0)
{
close(pipeA[1]);
dup2(pipeA[0],0);
close(pipeA[0]);
close(pipeB[0]);
dup2(pipeB[1],1);
close(pipeB[1]);
execlp("grep", "grep", "grep", (char *)NULL);
err_exit("error execing 'grep grep'\n");
}
if ((pidC = fork()) < 0)
err_exit("failed to fork (C)\n");
else if (pidC == 0)
{
close(pipeA[0]); // The second grep is not going to use the first pipe
close(pipeA[1]); // Ditto
close(pipeB[1]);
dup2(pipeB[0],0);
close(pipeB[0]);
execlp("grep", "grep", "b", (char *)NULL);
err_exit("error execing 'grep b'\n");
}
close(pipeA[0]); // The parent process is not using the pipes at all
close(pipeA[1]);
close(pipeB[0]);
close(pipeB[1]);
while (wait(0) != -1)
;
printf("Continuing here...\n");
sleep(3);
printf("That's enough of that!\n");
return 0;
}
static void err_exit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
When doctored to use /usr/bin
instead of /bin
, this program works OK on Mac OS X 10.7.3. 当尝试使用
/usr/bin
代替/bin
,此程序在Mac OS X 10.7.3上可以正常运行。 It lists three files and then generates the message about 'Continuing here': 它列出了三个文件,然后生成有关“在此处继续”的消息:
bzegrep
bzfgrep
bzgrep
Continuing here...
That's enough of that!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.