Яка різниця між & 6 та / dev / fd / 6?


11

Для читання з дескриптора файлів 6 я можу використовувати <&6або </dev/fd/6(ака /proc/self/fd/6). Зазвичай обидва працюють однаково добре. Однак якщо цей дескриптор файлу є сокетом, трапляються дивні речі. Наприклад:

$ 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

Тут lsпоказано, що дескриптор справді присутній. Але отримати доступ до даних неможливо таким чином. Якщо я використовую cat <&6замість цього, все знову працює добре.

Чим відрізняються обидва способи доступу до дескриптора файлу?

Чи є хороший спосіб отримати доступ до дескриптора, якщо число, якщо воно вказане в змінній? ( </dev/fd/$fdпрацював би, але <&$fdні.)

(Вищеописану ситуацію можна спостерігати на Linux, але не на OpenBSD. - Схоже, дескриптор файлів є звичайним пристроєм символів.)


1
Це дубльований один unix.stackexchange.com/q/98958/38906
cuonglm

2
Спасибі. Це пов'язано, але насправді не дублікат.
michas

Відповіді:


5

Це так, тому що зчитування з /dev/fd/записів, що представляють сокети, не реалізовано в Linux. Тут ви можете знайти досить непоганий опис міркувань. Таким чином, ви можете зателефонувати statза посиланням, і тому ви бачите це ls, але доступ навмисно заборонений.

Тепер для другої частини - навіщо bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345працює? Це тому, що сокет зчитується з API сокета / файлу, а не з /procфайлової системи. Це те, що я спостерігав:

  1. bash екземпляр, що працює у вашому терміналі, створює сокет з fd 6.
  2. Дитина bashбігає і дзвонить dup2(6, 0), щоб прикріпити ваш розетку як cat"s" stdin.
  3. Якщо dup2дзвінок не пройшов, кішка читає з stdin.

Ви можете відтворити та спостерігати за ним:

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

Якщо вам цікаво, чому bashдочірній процес має доступ до дескрипторів файлів fd 6 fork, і якщо вони не позначені для закриття exec, вони також не закриваються.


3

Щоб відповісти на ваше пряме запитання, " яка різниця ?":

Під час переадресації з <&6оболонки використовується dup2()системний виклик для дублювання дескриптора файлу. Коли ви (намагаєтесь) переадресувати </dev/fd/6, він використовуватиме open().

Ядро не підтримує open()сокети в /dev/fd; вони містяться в каталозі лише для інформації про декорування .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.