Qual è la differenza tra & 6 e / dev / fd / 6?


11

Per leggere dal descrittore di file 6 posso usare <&6o </dev/fd/6(aka /proc/self/fd/6). Di solito entrambi funzionano ugualmente bene. Tuttavia, se quel descrittore di file risulta essere un socket, accadono cose strane. Per esempio:

$ 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

Qui lsmostra che il descrittore è effettivamente presente. Ma l'accesso ai dati non è possibile in questo modo. Se uso cat <&6invece tutto funziona di nuovo bene.

Qual è la differenza tra entrambi i modi di accedere al descrittore di file?

C'è un buon modo per accedere a un descrittore se il numero è indicato in una variabile? ( </dev/fd/$fdfunzionerebbe, ma <&$fdnon lo fa.)

(La situazione di cui sopra può essere osservata su Linux, ma non su OpenBSD. - Sembra che quel descrittore di file sia un dispositivo a caratteri regolari lì.)



2
Grazie. È correlato ma in realtà non è un duplicato.
michas,

Risposte:


5

È perché la lettura da /dev/fd/voci che rappresentano socket non è implementata su Linux. Puoi trovare un buon commento sul ragionamento qui. Quindi puoi chiamare statil link, ed è per questo che lo vedi ls, ma l'accesso è deliberatamente vietato.

Ora per la seconda parte: perché bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345funziona? Questo perché socket viene letto dall'uso dell'API socket / file, non dal /procfilesystem. Questo è quello che ho visto accadere:

  1. bash l'istanza in esecuzione nel tuo terminale crea socket con fd 6.
  2. Il bambino bashcorre e chiama dup2(6, 0), al fine di collegare il socket come cat's stdin.
  3. Se la dup2chiamata non ha esito negativo, il gatto legge stdin.

Puoi riprodurlo e osservarlo con:

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

Se ti stai chiedendo perché il bashprocesso figlio abbia accesso a fd 6 - i descrittori di file sopravvivono forke se non sono contrassegnati per la chiusura exec, non vengono chiusi anche lì.


3

Per rispondere alla tua domanda diretta, " qual è la differenza ?":

Quando si reindirizza da <&6, la shell utilizza una dup2()chiamata di sistema per duplicare il descrittore di file. Quando (tenterai di) reindirizzare da </dev/fd/6, verrà utilizzato open().

Il kernel non supporta i open()socket in /dev/fd; sono presenti nella directory solo a scopo decorativo .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.