
Wenn der yes
Befehl kontinuierlich „y“ ausgibt, bis er beendet wird, wird er nie richtig ausgeführt? Wenn er nie ausgeführt wird, wie leitet er dann seine Ausgabe an den nächsten Befehl weiter??
Antwort1
Das yes
Programm schreibt gleichzeitig mit dem Leser in die Pipe. Wenn die Pipe leer ist, blockiert der Leser den Kernel und wartet read()
auf weitere Eingaben. Wenn die Pipe voll ist, blockiert der Schreibvorgang den Kernel und wartet darauf, write()
dass der Leser etwas Platz in der Pipe freigibt.
Der Kernel sendet SIGPIPE
einem Prozess ein Signal, wenn er versucht, in eine Pipe zu schreiben, die keinen Reader hat. Wenn der Leseprozess das Leseende der Pipe schließt (entweder explizit oder als Folge seiner Beendigung), wird der Schreibprozess das Signal empfangen, wenn er das nächste Mal versucht, in die Pipe zu schreiben SIGPIPE
.
Um dies zu veranschaulichen, betrachten Sie diese vereinfachte Version des yes
Programms, das einen kontinuierlichen Datenstrom von ausgibt y
. Dieses Programm unterscheidet sich von yes
dadurch, dass es eine Nachricht generiert, wenn es das SIGPIPE
Signal empfängt:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
static void handler(int sig) {
#define msg "received SIGPIPE signal, terminating\n"
write(2, msg, sizeof msg);
exit(1);
#undef msg
}
int main(void) {
// Instruct the kernel to call the handler() function when
// this process receives the SIGPIPE signal. The default behavior
// when this signal is received is for the process to terminate.
signal(SIGPIPE, handler);
for (;;) {
if (write(1, "y\n", 2) < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 2;
}
}
return 0;
}
Ich kann das Programm kompilieren und ausführen und sehe, dass es sich wie folgt verhält yes
:
$ gcc ex.c -o myes
$ ./myes
y
y
y
...
Wenn ich die Ausgabe an einen anderen Prozess weiterleite und dieser Prozess beendet wird (und das Leseende der Pipe geschlossen wird), myes
empfängt das Programm das SIGPIPE
Signal (wie durch die zugehörige Meldung angezeigt).
$ ./myes | head -n5
y
y
y
y
y
received SIGPIPE signal, terminating