& 6 ve / dev / fd / 6 arasındaki fark nedir?


11

Dosya tanımlayıcı 6'dan okumak için <&6veya </dev/fd/6(aka /proc/self/fd/6) kullanabilirsiniz. Genellikle her ikisi de eşit derecede iyi çalışır. Ancak, bu dosya tanımlayıcı bir soket olursa, garip şeyler olur. Örneğin:

$ bash -c 'ls -l /dev/fd/6;cat /dev/fd/6' 6</dev/tcp/localhost/12345
lrwx------ 1 michas michas 64 Jan 10 19:50 /dev/fd/6 -> socket:[315010]
cat: /dev/fd/6: No such device or address

Burada lstanımlayıcının gerçekten mevcut olduğunu gösterir. Ancak verilere bu şekilde erişmek mümkün değildir. Onun cat <&6yerine kullanırsam her şey tekrar iyi çalışır.

Dosya tanımlayıcıya erişmenin her iki yolu arasındaki fark nedir?

Bir değişkente verilirse tanımlayıcıya erişmenin iyi bir yolu var mı? ( </dev/fd/$fdişe yarar, ancak işe <&$fdyaramaz.)

(Yukarıdaki durum linux'da görülebilir, ancak OpenBSD'de görülemez. - Dosya tanımlayıcı orada normal bir karakter aygıtı gibi görünüyor.)



2
Teşekkürler. Alakalı ama gerçekten bir kopya değil.
michas

Yanıtlar:


5

Bunun nedeni /dev/fd/, soketleri temsil eden girişlerden okumak Linux'ta uygulanmadığıdır. Burada akıl yürütme konusunda oldukça iyi bir yazı bulabilirsiniz. Böylece statbağlantıyı arayabilirsiniz ve bu yüzdenls , ancak erişim kasıtlı olarak izin verilmiyor.

Şimdi ikinci kısım için - neden bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345çalışıyor? Bunun nedeni soketin dosya /procsistemi değil soket / dosya API'sı kullanılarak okunmasıdır . Bunun olduğunu gözlemledim:

  1. bash terminalinizde çalışan örnek fd 6 ile soket oluşturur.
  2. Çocuk bashçalışır ve aramaları dup2(6, 0), gibi soket takmak için cats' stdin.
  3. Eğer dup2çağrı başarısız olmadı, kedi okur stdin.

Şununla çoğaltabilir ve gözlemleyebilirsiniz:

netcat -lp 12345    # in another terminal session (GNU netcat)
strace -f -e trace=open,read,write,dup2 bash -c 'ls -l /dev/fd/6; cat <&6' \
 6</dev/tcp/localhost/12345

bashAlt işlemin neden fd 6 - dosya tanımlayıcılarına erişimi olduğunu merak ediyorsanız forkve kapanmak için işaretlenmediyse exec, orada da kapanmazlar.


3

Doğrudan sorunuzu yanıtlamak için " fark nedir?":

Yönlendirme yaptığınızda <&6, kabuk dup2()dosya tanımlayıcısını çoğaltmak için bir sistem çağrısı kullanır . Yönlendirme yaptığınızda (denemeye çalıştığınızda) </dev/fd/6kullanır open().

Çekirdek open()soketlerde desteklenmez /dev/fd; sadece dekorasyon bilgisi için dizinde bulunurlar .

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.