Was passiert, wenn das „Ja“ an einen anderen Befehl weitergeleitet wird?

Was passiert, wenn das „Ja“ an einen anderen Befehl weitergeleitet wird?

Wenn der yesBefehl 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 yesProgramm 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 SIGPIPEeinem 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 yesProgramms, das einen kontinuierlichen Datenstrom von ausgibt y. Dieses Programm unterscheidet sich von yesdadurch, dass es eine Nachricht generiert, wenn es das SIGPIPESignal 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), myesempfängt das Programm das SIGPIPESignal (wie durch die zugehörige Meldung angezeigt).

$ ./myes | head -n5
y
y
y
y
y
received SIGPIPE signal, terminating

verwandte Informationen