прокачка через стандартный разветвление

0

Я не могу понять, почему я могу успешно работать через одну вилку, но не через 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
    }
}
  • 4
    Есть много связанных вопросов. Краткий ответ: вы не закрываете достаточно близко файловые дескрипторы. Каждый из трех процессов должен закрыть 4 дескриптора канала после выполнения соответствующих вызовов dup2() . Если вы этого не сделаете, то стандартный ввод grep имеет два процесса, которые все еще могут записывать в него ( grep и wc ), поэтому grep никогда не получит EOF, поэтому wc никогда не получит EOF, поэтому все заклинено.
  • 1
    Не запускайте всю трубу на уровне 0, определите p1 на уровне 1; и p2 на уровне 2, и проблема решена. Кроме того, не смешивайте C & C ++ ...
Показать ещё 3 комментария
Теги:
pipe
fork

1 ответ

1
Лучший ответ

Как заявили 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
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню