Domanda

Questo codice sotto è per l'esecuzione di ls -l | wc -l. Nel codice, se commento vicino (p [1]) in padre, il programma si blocca, in attesa di input. Perché è così? Il bambino scrive l'output di ls su p1 e parent dovrebbe aver preso quell'output da p0.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

main ()
{
  int i;
  int p[2];
  pid_t ret;
  pipe (p);
  ret = fork ();

  if (ret == 0)
    {
      close (1);
      dup (p[1]);
      close (p[0]);
      execlp ("ls", "ls", "-l", (char *) 0);
    }

  if (ret > 0)
    {
      close (0);
      dup (p[0]);
      //Doubt, Commenting the line below does not work WHy?
      close (p[1]);
      wait (NULL);
      execlp ("wc", "wc", "-l", (char *) 0);
    }
}
È stato utile?

Soluzione

pipe + fork crea 4 descrittori di file, due sono input

Prima del fork hai una singola pipe con un input e un output.

Dopo il fork avrai un singolo tubo con due ingressi e due uscite.

Se hai due input per la pipe (su cui scrive un proc) e due output (da cui legge un proc), devi chiudere l'altro input o il lettore avrà anche un input per pipe che non si chiude mai.

Nel tuo caso il genitore è il lettore e, oltre all'estremità di output del pipe, ha un altro end o end di input aperto del pipe che roba potrebbe, in teoria , essere scritto a. Di conseguenza, la pipe non invia mai un eof, perché quando il bambino esce la pipe è ancora aperta a causa della fd inutilizzata del genitore.

Quindi i genitori si bloccano, aspettando per sempre che scriva a se stesso.

Altri suggerimenti

Nota che ' dup (p [1]) ' significa che hai due descrittori di file che puntano allo stesso file. Non chiude p [1] ; dovresti farlo esplicitamente. Allo stesso modo con ' dup (p [0]) '. Si noti che un descrittore di file che legge da una pipe restituisce zero byte (EOF) solo quando non ci sono descrittori di file di scrittura aperti per la pipe; fino alla chiusura dell'ultimo descrittore di scrittura, il processo di lettura si bloccherà indefinitamente. Se dup () alla fine della scrittura, ci sono due descrittori di file aperti alla fine della scrittura, ed entrambi devono essere chiusi prima che il processo di lettura ottenga EOF.

Inoltre non è necessario o non si desidera che la chiamata wait () nel codice. Se l'elenco ls è più grande di quanto una pipe possa contenere, i tuoi processi si bloccheranno, con il bambino in attesa del completamento di ls e ls in attesa di il bambino continuerà a leggere i dati che ha scritto.

Quando il materiale ridondante viene rimosso, il codice di lavoro diventa:

#include <unistd.h>

int main(void)
{
    int p[2];
    pid_t ret;
    pipe(p);
    ret = fork();

    if (ret == 0)
    {
        close(1);
        dup(p[1]);
        close(p[0]);
        close(p[1]);
        execlp("ls", "ls", "-l", (char *) 0);
    } 
    else if (ret > 0)
    {
        close(0);
        dup(p[0]);
        close(p[0]);
        close(p[1]);
        execlp("wc", "wc", "-l", (char *) 0);
    }
    return(-1);
}

Su Solaris 10, questo viene compilato senza preavviso con:

Black JL: gcc -Wall -Werror -Wmissing-prototypes -Wstrict-prototypes -o x x.c
Black JL: ./x
      77
Black JL:

Se il bambino non chiude p [1] , allora FD è aperto in due processi: padre e figlio. Alla fine il genitore lo chiude, ma il bambino non lo fa mai, quindi l'FD rimane aperto. Pertanto, qualsiasi lettore di quel FD (il bambino in questo caso) aspetterà per sempre nel caso in cui ci sarà più scrittura su di esso ... non lo è, ma il lettore semplicemente NON CONOSCE! -)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top