Problemi usando DUP2 per fare un programma C Eseguire un comando come 'LS /Bin | grep grep | grep b '

StackOverflow https://stackoverflow.com/questions/9459627

  •  13-11-2019
  •  | 
  •  

Domanda

Ho problemi a usare DUP2 per fare in modo che il programma CA eseguisca un comando come ad esempio ls /bin | grep grep | grep b. Quando commenta il terzo comando e il tubo associato che esegue ls /bin | grep grep Bene, ma con l'ultimo comando ritorna subito. Inoltre, quando inserisco "PS", i processi sono ancora in esecuzione. Penso che sia dovuto a come chiudo i tubi. Il mio codice è di seguito:

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;
}
È stato utile?

Soluzione

Non stai chiudendo abbastanza descrittori di file.

/* 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; 
}

Perché non hai chiuso pipeA nel secondo grep, finisci con il primo grep in attesa di input dal tubo il secondo grep Ha ancora aperto, anche se il processo non lo scriverà. Per questo motivo, il primo grep non finisce, quindi il secondo non finisce neanche, anche se il ls Completa. Questi commenti si applicherebbero anche se il processo genitore chiudesse le sue copie dei tubi, come fa il codice corretto.

Si noti come si finisce per chiudere tutti e 4 i descrittori restituiti dalle due chiamate a pipe() In ciascuno dei quattro processi: tre figli e il processo dei genitori.

Questo lascia un problema residuo: la gerarchia di processo è sottosopra a causa del tuo uso aconvenzionale di if (pidA = fork()). Hai un processo per bambini in attesa dei suoi genitori. Devi usare:

if ((pidA = fork()) == 0)
{
    /* Be childish */
}

Allo stesso modo per ciascuno degli altri due processi. Dovresti anche controllare il pipe() chiama e il fork() richiede un fallimento, solo per essere sicuri.

#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);
}

Se dotato di usare /usr/bin invece di /bin, questo programma funziona bene su Mac OS X 10.7.3. Elenca tre file e quindi genera il messaggio su "Continua qui":

bzegrep
bzfgrep
bzgrep
Continuing here...
That's enough of that!
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top