Welche Wahrscheinlichkeitsverteilung modelliert diese Rennbedingung?

10

Betrachten Sie den folgenden Befehl : bash -c "echo x; cat 1" | tee 1.

Mein Verständnis ist, dass es in eine neue Shell xverzweigen, in stdout schreiben, file 1 not foundin stderr schreiben , die Steuerung beenden und an den übergeordneten Prozess zurückgeben und xin stdout und in schreiben würde 1. Daher würde ich erwarten, dass die endgültige Ausgabe xerfolgt und die Datei 1genau die Zeichenfolge enthält x.

Dies ist jedoch nicht der Fall. Tatsächlich 1enthält die Datei normalerweise mindestens zwei Instanzen von xund manchmal Tausende von Zeilen von xs. Bei einem Batch-Test, bei dem der Befehl zehntausend Mal ausgeführt wurde, xbetrug die durchschnittliche Anzahl der in die Datei geschriebenen s 52,3 und der Median 1. Welcher Mechaniker verursacht dies? Welche Wahrscheinlichkeitsverteilung modelliert dieses Verhalten? Ich vermute, dass es bedingt geometrisch und ansonsten einheitlich ist.

Will Sherwood
quelle
3
Dies hat mit dem Zeitpunkt der Ausführung der linken und rechten Seite der Pipeline zu tun. Beide werden gleichzeitig oder in der Nähe gestartet. Wenn teedie Datei zum Schreiben geöffnet wurde, bevor catsie zum Lesen geöffnet wurde, enthält die Datei möglicherweise viele x-es. In diesem Fall würde die "Schleife" immer dann enden, wenn das catLesen schneller als das teeSchreiben erfolgt und das Ende der Datei erreicht.
Kusalananda
Nach begrenzten Tests xbetrug die durchschnittliche Anzahl der in die Datei geschriebenen s 4,35. Ich denke, es wird sehr von der Maschinenlast abhängen.
Renan

Antworten:

1

Dies ist eine sehr merkwürdige Sache, deshalb habe ich versucht, sie mit Hilfe von Strace zu untersuchen. Führen Sie Ihren Befehl 1000 Mal in einer Schleife aus:

mkdir {000..999}
for i in {000..999}; do
echo $i
(cd $i; strace -f -o trace.log bash -c 'bash -c "echo x; cat 1" | tee 1 >/dev/null'; )
done

Fand die Datei mit den meisten Zeilen ( wc -l */1 | sort -nr | head -n2) und überprüfte die entsprechende trace.log. Ich kann sicherlich viele sehen:

7567  <... read resumed> "x\n", 8192)   = 2
7567  write(1, "x\n", 2)                = 2
7567  write(3, "x\n", 2)                = 2
7567  read(0,  <unfinished ...>
7568  read(3, "x\n", 131072)            = 2
7568  write(1, "x\n", 2)                = 2
7567  <... read resumed> "x\n", 8192)   = 2
7567  write(1, "x\n", 2)                = 2
7567  write(3, "x\n", 2)                = 2
7567  read(0,  <unfinished ...>
7568  read(3, "x\n", 131072)            = 2
7568  write(1, "x\n", 2)                = 2
7567  <... read resumed> "x\n", 8192)   = 2
7567  write(1, "x\n", 2)                = 2
7567  write(3, "x\n", 2)                = 2
7567  read(0,  <unfinished ...>

Wo 7567 ist tee 1und 7568 ist cat 1. Die beiden wechseln sich definitiv ab, also dreht sich, wie vermutet, alles um den Zeitpunkt der Ausführung (und ich stelle mir eine Kontextumschaltung vor) der beiden Befehle.

Chutz
quelle