2013-05-05 3 views
16

Dieses Programm erzeugt SIGPIPE, nachdem es nach einer zufälligen Zeit an "head -n 1" weitergeleitet wurde. Ich verstehe, dass wir, weil wir mehr nach "head -n 1" nach der ersten Zeile füttern, erwarten würden, dass es SIGPIPE generiert, aber stattdessen wird es zu einer zufälligen Zahl (normalerweise> 20 und < 200) vor dem Exit machen. Irgendeine Idee warum?Warum generiert dieses C-Programm SIGPIPE später als erwartet?

#include <stdio.h> 
#include <stdlib.h> 

main() 
{ 
    int i; 
    char *s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"; 

    i = 0; 
    while (1) { 
    fputs(s, stdout); 
    fflush(stdout); 
    fprintf(stderr, "Iteration %d done\n", i); 
    i++; 
    } 
} 

Dies ist keine Hausaufgaben, nur etwas in den Notizen meines Professors, die ich nicht verstehe.

+0

Ehm, ** 'const' **' char * s = ... ' –

+2

Es braucht Zeit, um den Tabak stopfen. – Kaz

Antwort

8

Es ist die Launen der Planung.

Ihr Hersteller - nennen wir es alphabeta - kann für eine gewisse Zeit laufen, bevor head lesen und beenden kann (wodurch die Leitung unterbrochen wird).

Das "einige Zeit" ist natürlich variabel.

Manchmal alphabeta läuft 20 mal vor head kann stdin lesen und beenden. Manchmal 200 mal. Auf meinem System manchmal 300 oder 1000 oder 2000 mal. In der Tat kann es theoretisch bis zu der Kapazität des Rohres reichen, das den Erzeuger und den Verbraucher verbindet.

Zur Demonstration, lassen Sie sich eine gewisse Verzögerung einführen, so dass wir einigermaßen sicher sein können, dass head in einem Lese stecken() vor alphabeta eine einzige Zeile Ausgabe erzeugt:

so$ { sleep 5; ./alphabeta; } | head -n 1 
ABCDEFGHIJKLMNOPQRSTUVWXYZ 
Iteration 0 done 

(NB ist es nicht garantiert, dass alphabeta wird Nur einmal in obigem iterieren, aber auf einem entladenen System, dies wird mehr oder weniger immer der Fall sein: head wird bereit sein, und sein Lesen/Beenden wird mehr oder weniger sofort geschehen.)

Uhr statt, was passiert, wenn wir künstlich head verzögern:

so$ ./alphabeta | { sleep 2; head -n 1; } 
Iteration 0 done 
... 
Iteration 2415 done # <--- My system *pauses* here as pipe capacity is reached ... 
Iteration 2416 done # <--- ... then it resumes as head completes its first read() 
... 
Iteration 2717 done # <--- pipe capacity reached again; head didn't drain the pipe 
ABCDEFGHIJKLMNOPQRSTUVWXYZ 

Als beiseite, @R .. ist ganz richtig in seinen Ausführungen, dass SIGPIPE synchron ist. In Ihrem Fall wird das erste fflush-induzierte Schreiben in eine unterbrochene Leitung (nachdem head beendet wurde) synchron das Signal erzeugen. Dies ist documented behavior.

4

Ich denke, es ist einfach, weil Signale asynchron sind.

Update: Wie andere darauf hingewiesen haben, sind sie (genauer gesagt viele, einschließlich SIGPIPE) nicht. Dies war eine unbedachte Antwort :)

+0

Nein, es ist die Pufferung der Festplatte. –

+5

SIGPIPE ist ein synchrones Signal. –

+0

@R .. 'stdio' puffert nicht hinter einem' fflush'. – Kevin

0

Sockets schreibt sind gepuffert und asynchron, so dass Sie im Allgemeinen nicht erhalten einen Fehler von einem bestimmten Schreiben bis zu einem folgenden lesen oder schreiben).

+5

Ich bin mir nicht sicher, warum Socket-Schreibvorgänge Material für eine Frage über Piped-Ausgabe sind. –

0

Der Befehl head verwendet stdio, um stdin zu lesen, und daher kehrt der erste getc erst zurück, wenn der Puffer voll ist oder EOF, je nachdem, was zuerst eintritt.

+0

Sie können dies mit strace überprüfen. –

+1

Nein, es ist Rohrkapazität und Planung. Siehe meine Antwort. – pilcrow

+0

Wie pilcrow sagte, ist es Zeitplan. Der Pipe Buffer des Kernels (typischerweise 64-128 KiB) füllt sich in diesem Fall nicht, da nur etwa 200 * 27 = 5,4 KB an Daten geschrieben werden. –

Verwandte Themen