Meine Frage ist, wie man die Prozessausführung in Bezug auf Rohre und speziell die Implementierung der wait
/waitpid
Funktion steuert.C in Unix: Gabel, waitpid und Rohre
Wenn ich eine Pfeife für den folgenden Befehl ls | head -3
, ich folgenden:
- ich das Rohr schaffen, Gabel des Prozesses
- Für das Kind, ein Kind zu schaffen, ich nenne dup2 für stdin, I führe den
head -3
Befehl Ausgangsseite des Rohrs in dem - für die Eltern-Kind-Schließen, ich rufe dup2 für stdout, führe ich den
ls
Befehl, Schließen die Eingangsseite des Rohres in den übergeordneten
Meine Frage: based on this discussion, ich muss warten, bis das Kind die Ausführung abgeschlossen hat, d. H. Die Ausführung von head -3
. Aber wie/wo kann ich die waitpid
Funktion so implementieren, dass sie nicht in Konflikt mit dem close[]
Befehl steht?
Basierend auf this great text, die Beschreibung lautet:
Wenn die Eltern wollen Daten aus dem Kind zu erhalten, sollte es FD1 schließen, und das Kind sollte fd0 schließen. Wenn das übergeordnete Element Daten an das untergeordnete Element senden möchte, sollte es fd0 schließen, und das untergeordnete Element sollte fd1 schließen. Da die Deskriptoren zwischen dem Elternteil und dem Kind geteilt werden, sollten wir immer sicher sein, das Ende des Rohrs zu schließen, mit dem wir uns nicht befassen. In einer technischen Anmerkung wird der EOF niemals zurückgegeben, wenn die unnötigen Enden der Pipe nicht explizit geschlossen werden.
So muss das Kind auf die Eltern warten, um die Pipe vor der Ausführung abzuschließen.
Ich habe auch Beispiele gesehen, wo zwei Gabeln für einen Prozess mit Rohr hergestellt werden. Kann es der Zweck sein, Zombie-Prozesse zu vermeiden, genau wie die Beschreibung in meiner Kopie von APUE ch.8?
Betrachten Sie den folgenden Code-Implementierung:
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
int main()
{
int pid, status;
int fd[2];
char *com1[2];
char *com2[3];
com1[0] = "ls";
com1[1] = NULL;
com2[0] = "head";
com2[1] = "-3";
com2[2] = NULL;
pipe(fd);
if((pid = fork()) == -1)
{
printf("fork error");
exit(1);
}
if(pid == 0)
{
/* Child process closes up output side of pipe */
dup2(fd[0], 0);
close(fd[1]);
execvp(com2[0], com2);
}
else
{
/* if(waitpid(0, WIFEXITED(&status), 0) != pid)
{
printf("wait error");
}
is this even needed here? */
/* Parent process closes up input side of pipe */
dup2(fd[1], 1);
close(fd[0]);
execvp(com1[0], com1);
}
exit(0);
}
Ich muss zugeben, dass ich durch viele ähnliche Fragen auf Stack hier ausgesehen haben. Fast alle von ihnen sind jedoch von besonderem Inhalt. Nach was ich suche, sind Erklärungen von Prinzipien und Kombinationen der Funktionen. Vielen Dank für Ihre Zeit!
Wenn Sie wollen, dass der übergeordnete Prozess Ausführung fortzusetzen, Sie müssen * zwei * untergeordnete Prozesse erstellen: einen für den Befehl "ls" und einen für den Befehl "head". Und nein das Kind (in Ihrem Programm) muss nicht auf das Elternteil warten, wenn es nichts gibt, das zurzeit aus dem Rohr zu lesen ist, werden alle blockierungsfreien Lesungen (die die Standardeinstellung sind) einfach blockieren, bis Daten zu lesen sind oder ein Fehler tritt ein. –
@JoachimPileborg: "Alle nicht blockierenden Messwerte werden blockiert"? –
Ehm ... Alle non non-blocking reads werden blockieren Ich meine ... :) –