Dua jendela, pengguna yang sama, dengan bash prompt. Di jendela-1 ketik:
$ mkfifo f; exec <f
Jadi bash sekarang mencoba membaca dari file descriptor 0, yang dipetakan ke pipa bernama f
. Di jendela-2 ketik:
$ echo ls > f
Sekarang window-1 mencetak ls dan kemudian shellnya mati. Mengapa?
Eksperimen selanjutnya: buka window-1 lagi dengan exec <f
. Di jendela-2 ketik:
$ exec 3>f
$ echo ls >&3
Setelah baris pertama di atas, jendela-1 bangun dan mencetak prompt. Mengapa? Setelah baris kedua di atas, window-1 mencetak ls
output dan shell tetap hidup. Mengapa? Bahkan, sekarang di window-2, echo ls > f
tidak menutup shell window-1.
Jawabannya pasti ada hubungannya dengan keberadaan file descriptor 3 dari window-2 yang mereferensikan pipa bernama ?!
file-descriptors
fifo
Fixee
sumber
sumber
exec <f
,bash
tidak mencoba membaca darif
, itu pertama-tama mencoba untuk membukanya . Tidakopen()
akan kembali sampai ada beberapa proses melakukan buka lagi dalam mode tulis ke pipa (pada titik mana pipa akan dipakai, dan shell akan membaca input dari itu).exec 3>f
dijalankan, shell pertama kemudian memberikan prompt. (Poin minor, maksud Anda "dalam mode tulis " dalam komentar Anda?)Jawaban:
Ini ada hubungannya dengan penutupan deskriptor file.
Dalam contoh pertama Anda,
echo
tulis ke aliran output standar yang dibuka shell untuk menghubungkannyaf
, dan ketika berakhir, deskriptornya ditutup (oleh shell). Di sisi penerima, shell, yang membaca input dari aliran input standar (terhubung kef
) membacals
, berjalanls
dan kemudian berakhir karena kondisi akhir file pada input standarnya.Kondisi akhir file terjadi karena semua penulis ke pipa bernama (hanya satu dalam contoh ini) telah menutup ujung pipa mereka.
Dalam contoh kedua,
exec 3>f
membuka file descriptor 3 untuk menulis kef
, kemudianecho
menulisls
untuk itu. Itu shell yang sekarang memiliki deskriptor file dibuka, bukanecho
perintah. Deskriptor tetap terbuka sampai Anda melakukannyaexec 3>&-
. Di sisi penerima, shell, yang membaca input dari aliran input standarnya (terhubung kef
) membacals
, berjalanls
dan kemudian menunggu lebih banyak input (karena aliran masih terbuka).Aliran tetap terbuka karena semua penulis untuk itu (shell, via
exec 3>f
, danecho
) belum menutup ujung pipa mereka (exec 3>f
masih berlaku).Saya telah menulis tentang di
echo
atas seolah-olah itu adalah perintah eksternal. Kemungkinan besar dibangun ke dalam shell. Efeknya tetap sama.sumber
Tidak ada banyak untuk itu: ketika tidak ada penulis ke pipa, itu terlihat tertutup bagi pembaca, yaitu mengembalikan EOF ketika membaca dan memblokir ketika dibuka.
Dari halaman manual Linux (
pipe(7)
, tetapi lihat jugafifo(7)
):Menutup akhir penulisan adalah apa yang secara implisit terjadi pada akhir
echo ls >f
, dan seperti yang Anda katakan, dalam kasus lain, deskriptor file tetap terbuka.sumber
Setelah membaca dua jawaban dari @ Kusalananda dan @ikkachu, saya pikir saya mengerti. Di jendela-1, shell sedang menunggu sesuatu untuk membuka kedua ujung pipa dan kemudian menutupnya. Setelah akhir penulisan dibuka, shell di window-1 mencetak prompt. Setelah akhir penulisan ditutup, shell mendapat EOF dan mati.
Di sisi jendela-2 kita memiliki dua situasi yang dijelaskan dalam pertanyaan saya: dalam situasi pertama dengan
echo ls > f
, tidak ada file deskriptor 3, jadi kami telahecho
memijah, dan itustdin
danstdout
terlihat seperti ini:Kemudian
echo
berakhir dan shell menutup kedua deskriptor. Karena file descriptor 1 ditutup dan referensif
, akhir penulisanf
ditutup dan yang menyebabkan EOF ke jendela-1.Dalam situasi kedua, kami menjalankan
exec 3>f
shell kami, menyebabkan shell mengambil lingkungan ini:Sekarang kita jalankan
echo ls >& 3
dan shell mengalokasikan file deskriptor untukecho
sebagai berikut:Kemudian shell menutup tiga deskriptor di atas, termasuk
f
, tetapif
masih memiliki referensi untuk itu dari shell itu sendiri. Inilah perbedaan penting. Menutup deskriptor 3 denganexec 3>&-
akan menutup referensi terbuka terakhir dan menyebabkan EOF ke jendela-1, seperti yang dicatat oleh @Kusalananda.sumber