[英]Execute the command " ls -l | grep ^d | wc " using dup2 and pipe()
[英]Trouble using dup2 to make a C 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
ls /bin | grep grep
很好,但是使用最后一個命令,它會立即返回。 同樣,當我輸入“ ps”時,進程仍在運行。 我認為這是由於我如何關閉管道。 我的代碼如下:
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;
}
您沒有關閉足夠的文件描述符。
/* 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;
}
因為您沒有在第二個grep
關閉pipeA
,所以最后一個第一個grep
等待來自第二個grep
仍然打開的管道的輸入,即使該進程不會對其進行寫入。 因此,第一個grep
不會完成,因此第二個grep
也不會完成-即使ls
已經完成。 即使父進程關閉了其管道副本,這些注釋也將適用-就像更正后的代碼一樣。
請注意,如何最終關閉四個進程中的每個進程(三個子進程和父進程pipe()
的兩次調用pipe()
返回的所有4個描述符。
這留下了一個殘留的問題-由於您常規使用if (pidA = fork())
因此流程層次結構顛倒了。 您有一個子進程正在等待其父進程。 您需要使用:
if ((pidA = fork()) == 0)
{
/* Be childish */
}
其他兩個過程中的每個過程類似。 為了確保安全,您還應該檢查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);
}
當嘗試使用/usr/bin
代替/bin
,此程序在Mac OS X 10.7.3上可以正常運行。 它列出了三個文件,然后生成有關“在此處繼續”的消息:
bzegrep
bzfgrep
bzgrep
Continuing here...
That's enough of that!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.