Adlandırılmış kanallar, dosya tanımlayıcılar ve EOF


10

İki pencere, aynı kullanıcı, bash istemleri. Pencere-1 yazın:

$ mkfifo f; exec <f

Bash şimdi adlandırılmış yöneltme ile eşlenen 0 dosya tanımlayıcısından okumaya çalışıyor f. Pencere-2 yazın:

$ echo ls > f

Şimdi window-1 bir ls yazdırır ve sonra kabuk ölür. Neden?

Sonraki deneme: window-1 ile tekrar açın exec <f. Pencere-2 yazın:

$ exec 3>f
$ echo ls >&3

Yukarıdaki ilk satırdan sonra, pencere-1 uyanır ve bir istem yazdırır. Neden? Yukarıdaki ikinci satırdan sonra, pencere-1 çıktıyı yazdırır lsve kabuk canlı kalır. Neden? Aslında, şimdi pencere-2'de, echo ls > fpencere-1 kabuğunu kapatmaz.

Cevabın , adlandırılmış yöneltmeye referansta bulunan pencere-2 dosya tanımlayıcı 3'ün varlığıyla ilgili olması gerekir.


1
Sonra exec <f, bashteşebbüs değildir okumak gelen f, ilk çalışıyor açmak onu. open()Boruya yazma modunda başka bir açık (ki borunun örneği olacak etmektedir, ve kabuk ondan giriş okuyacaktır) yaparak bir süreç vardır kadar döndürmez.
Stéphane Chazelas

Mükemmel nokta, @ StéphaneChazelas. Bu nedenle, bir kez exec 3>fçalıştırıldığında, ilk kabuk bir istem verir. (Küçük bir nokta, yorumunuzda " yazma modunda" demek istediniz ?)
Fixee

1
Evet üzgünüm. Son 5 dakikasından hemen önce düzenlendi
Stéphane Chazelas

Yanıtlar:


12

O ilgisi var kapanış dosya tanımlayıcısı.

İlk örneğinizde, echokabuğun bağlanmak için açtığı standart çıkış akışına yazar fve sona erdiğinde tanımlayıcısı kapatılır (kabuk tarafından). Alıcı uçta, standart giriş akışından (bağlı f) girişi okuyan kabuk, standart girişindeki dosya sonu durumu nedeniyle okur ls, çalışır lsve sonlandırılır.

Dosya sonu koşulu, adlandırılmış kanaldaki tüm yazarların (bu örnekte yalnızca bir tanesi) kanalın sonunu kapatması nedeniyle oluşur.

İkinci örneğinizde, exec 3>fdosya tanımlayıcı 3'ü yazmak için açar f, sonra echoyazar ls. echoKomut değil, dosya tanımlayıcısının açıldığı kabuk . Tanımlayıcı sizinkine kadar açık kalır exec 3>&-. Alıcı uçta, standart giriş akışından (bağlı f) girişi okuyan kabuk okur ls, çalışır lsve daha fazla giriş bekler (akış hala açık olduğundan).

Akış kalıntılarıyla buna yazarlar (aracılığıyla kabuktan, çünkü açık exec 3>fve echo) sahip olup , borunun kendi ucu kapalı ( exec 3>fhâlâ yürürlükte olan).


echoYukarıda harici bir komutmuş gibi yazdım . Büyük olasılıkla kabuk içine inşa edilmiştir. Etkisi yine de aynıdır.


6

Fazla bir şey yok: boruya yazar olmadığında, okuyuculara kapalı görünüyor, yani okunduğunda EOF döndürüyor ve açıldığında engelliyor.

Linux kılavuz sayfasından ( pipe(7), ayrıca bakınız fifo(7)):

Bir borunun yazma ucuna atıfta bulunan tüm dosya tanımlayıcıları kapatıldıysa, read(2)borudan yapılacak bir girişim dosya sonunu görecektir ( read(2)0 döndürecektir).

Yazma sonunun kapatılması, sonunda dolaylı olarak gerçekleşir echo ls >fve dediğiniz gibi, diğer durumda, dosya tanımlayıcı açık tutulur.


Java (ve diğer OO dilleri) sayılarına benzer bir tür görünüyor! Gerçi mantıklı.
Fixee

2

@Kusalananda ve @ikkachu'dan gelen iki cevabı okuduktan sonra anlıyorum. Pencere-1'de, kabuk hem borunun yazma ucunu açmak hem de kapatmak için bir şey bekliyor. Yazma sonu açıldığında, pencere-1'deki kabuk bir istem yazdırır. Yazma sonu kapatıldığında, kabuk EOF alır ve ölür.

İlk durumda olan: pencere-2 tarafta biz iki durum soruma açıklanan var echo ls > forada biz var hiçbir dosya tanımlayıcı 3 olduğu, echobunun yumurtlama ve stdinve stdoutgöz böyle:

0 --> tty
1 --> f

Sonra echosona erer ve kabuk her iki tanımlayıcıyı da kapatır. Dosya tanıtıcısı 1 kapalı olduğundan ve başvurduğundan f, yazma sonu fkapatılır ve bu da EOF'un pencere-1'e neden olur.

İkinci durumda, exec 3>fkabuğumuza koşarak kabuğun bu ortamı almasına neden oluyoruz:

bash:
0 --> tty
1 --> tty
2 --> tty
3 --> f

Şimdi çalıştırıyoruz echo ls >& 3ve kabuk dosya tanımlayıcılarını echoaşağıdaki gibi tahsis ediyor:

echo:
0 --> tty
1 --> f     # because 3 points to f
2 --> tty

Daha sonra kabuk , kabuğun kendisinden de dahil olmak üzere f, fyine de üç tanımlayıcıyı kapatır . Bu önemli fark. Tanımlayıcının 3 kapatılması exec 3>&-son açık referansı kapatır ve @Kusalananda'nın belirttiği gibi bir EOF'un pencere-1'e neden olur.


Bu, değiştirmek için iyi bir tasarım nedeni olmadıkça ilk üç dosya tanımlayıcısını neden yalnız bırakmanız gerektiğinin iyi bir örneğidir. Diğer kabuğa giriş tanımlayıcısı (0) olan tanımlayıcıyı (1) kullandığınızda, yalnızca boruyu (ve o veri akışıyla ne yaptığınızı) kapatmazsınız, aynı zamanda girdiyi ikinciye de kapatırsınız. Sonlandırılmasına neden olan kabuk. Bu iyi, ama sadece bilerek yapıyorsanız. Daha yüksek numaralı dosya tanımlayıcıları kullanmak, bunun gibi yan etkileri önler çünkü hiçbir şey bunların belirli bir durumda veya tanımlanmış olmasını beklemez.
Joe

Dürüst olmak gerekirse, bu yorumda ne söylemeye çalıştığımdan emin değilim, sadece sileceğim.
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.