Quelle distribution de probabilité modélise cette condition de concurrence?

10

Considérez la commande suivante: bash -c "echo x; cat 1" | tee 1.

Ma compréhension est qu'il se bifurquerait vers un nouveau shell, écrirait xsur stdout, écrirait file 1 not foundsur stderr, quitterait et retournerait le contrôle au processus parent, et écrirait xsur stdout et vers 1. Par conséquent, je m'attendrais à ce que la sortie finale soit x, et le fichier 1contient exactement la chaîne x.

Cependant, ce n'est pas le cas. En réalité, le fichier 1contient généralement au moins deux instances x, et parfois des milliers de lignes de xs. Lors d'un test par lots d'exécution de la commande dix mille fois, le nombre moyen de xs écrits dans le fichier était de 52,3 et la médiane était de 1. Quel mécanicien est à l'origine de cela? Quelle distribution de probabilité modélise ce comportement? Je soupçonne qu'il est conditionnellement géométrique et autrement uniforme.

Will Sherwood
la source
3
Cela concerne le moment de l'exécution des côtés gauche et droit du pipeline. Les deux démarrent simultanément ou à proximité. Si teea ouvert le fichier pour l'écriture avant de l' catouvrir pour la lecture, vous pouvez obtenir plusieurs x-es dans le fichier. Dans ce cas, la "boucle" se terminait chaque fois que la catlecture était plus rapide que l' teeécriture, atteignant la fin du fichier.
Kusalananda
De tests limités ici, le nombre moyen de xs écrits dans le fichier était de 4,35. Je suppose que cela dépendra beaucoup de la charge de la machine.
Renan

Réponses:

1

Ceci est très curieux, alors j'ai essayé d'enquêter avec l'aide de Strace. Exécutez votre commande en boucle 1000 fois:

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

Trouvé le fichier avec le plus de lignes ( wc -l */1 | sort -nr | head -n2) et vérifié le correspondant trace.log. Je peux certainement voir beaucoup de:

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 ...>

Où 7567 est tee 1et 7568 est cat 1. Les deux sont définitivement en alternance, alors oui, comme on le soupçonne, il s'agit du moment de l'exécution (et j'imagine le changement de contexte) des deux commandes.

chutz
la source