Distribusi probabilitas apa yang memodelkan kondisi balapan ini?

10

Pertimbangkan perintah berikut: bash -c "echo x; cat 1" | tee 1.

Pemahaman saya adalah bahwa ia akan bercabang ke shell baru, menulis xke stdout, menulis file 1 not foundke stderr, keluar dan mengembalikan kontrol ke proses induk, dan menulis xke stdout dan ke 1. Oleh karena itu, saya akan mengharapkan hasil akhir x, dan file tersebut 1berisi string x.

Namun, ini bukan masalahnya. Pada kenyataannya, file 1biasanya berisi setidaknya dua contoh x, dan kadang-kadang ribuan baris xs. Pada tes batch menjalankan perintah sepuluh ribu kali, jumlah rata-rata xs ditulis ke file adalah 52,3, dan median adalah 1. Mekanik apa yang menyebabkan ini? Distribusi probabilitas apa yang memodelkan perilaku ini? Saya menduga bahwa itu adalah geometris kondisional dan seragam.

Will Sherwood
sumber
3
Ini ada hubungannya dengan waktu pelaksanaan sisi kiri dan kanan pipa. Keduanya dimulai secara bersamaan, atau dekat dengannya. Jika teetelah membuka file untuk ditulis sebelum catmembukanya untuk dibaca, Anda mungkin mendapatkan banyak x-es dalam file tersebut. Dalam hal ini, "perulangan" akan berakhir kapan saja catmembaca lebih cepat daripada teemenulis, mencapai akhir file.
Kusalananda
Dari pengujian terbatas di sini, jumlah rata-rata yang xditulis ke file adalah 4,35. Saya kira itu akan sangat tergantung pada beban mesin.
Renan

Jawaban:

1

Ini sangat aneh, jadi saya mencoba untuk menyelidikinya dengan bantuan strace. Jalankan perintah Anda dalam satu lingkaran 1000 kali:

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

Menemukan file dengan baris terbanyak ( wc -l */1 | sort -nr | head -n2), dan memeriksa yang sesuai trace.log. Saya pasti bisa melihat banyak:

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

Di mana 7567 adalah tee 1dan 7568 adalah cat 1. Keduanya pasti berganti-ganti, jadi ya, seperti yang diduga, ini semua tentang waktu pelaksanaan (dan saya membayangkan konteks beralih) dari dua perintah.

chutz
sumber