Я не могу понять, почему я могу успешно работать через одну вилку, но не через 2. Первый пример дает ожидаемый результат, эквивалентный "ps -A | grep bash", а второй пример должен содержать вывод "ps [CN00 ] | grep bash | wc -l ", который будет просто числом строк, созданных первым выходом. Вместо этого он не дает выхода и просто зависает.
Это работает:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
int p1[2], p2[2];
pipe(p1); pipe(p2);
pid_t pID;
pID = fork();
if (pID == 0)
{
close(p2[0]);
dup2(p2[1], 1);
close(p2[1]);
execlp("ps", "ps", "-A", 0); // print all processes
}
else
{
wait(pID);
close(p2[1]);
dup2(p2[0],0);
close(p2[0]);
execlp("grep", "grep", "bash", NULL); // search for bash (in process list)
}
}
Но это не так:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
int p1[2], p2[2];
pipe(p1); pipe(p2);
pid_t pID;
pID = fork();
if (pID == 0)
{
pID = fork();
if (pID == 0)
{
close(p2[0]);
dup2(p2[1], 1);
execlp("ps", "ps", "-A", 0); // print all processes
}
else
{
wait(pID);
close(p2[1]);
dup2(p2[0],0);
close(p1[0]);
dup2(p1[1], 1);
execlp("grep", "grep", "bash", 0); // search for bash (in process list)
}
}
else
{
wait(pID);
close(p1[1]);
dup2(p1[0],0);
execlp("wc", "wc", "-l", 0); // count lines
}
}
Как заявили moeCoke и Leffeir, если вы меняете одну строчку в своем коде, она работает абсолютно нормально.
#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
int p1[2], p2[2];
pipe(p1);
pid_t pID;
pID = fork();
if (pID == 0)
{
pipe(p2); // <-- call pipe for p2 here ---
pID = fork();
if (pID == 0)
{
close(p2[0]);
dup2(p2[1], 1);
execlp("ps", "ps", "-A", 0); // print all processes
}
else
{
wait(pID);
close(p2[1]);
dup2(p2[0],0);
close(p1[0]);
dup2(p1[1], 1);
execlp("grep", "grep", "p", 0); // search for bash (in process list)
}
}
else
{
wait(pID);
close(p1[1]);
dup2(p1[0],0);
execlp("wc", "wc", "-l", 0); // count lines
}
}
dup2()
. Если вы этого не сделаете, то стандартный вводgrep
имеет два процесса, которые все еще могут записывать в него (grep
иwc
), поэтомуgrep
никогда не получит EOF, поэтомуwc
никогда не получит EOF, поэтому все заклинено.