Qual é a diferença entre & 6 e / dev / fd / 6?

11

Para ler o descritor de arquivo 6, posso usar <&6 ou </dev/fd/6 (também conhecido como /proc/self/fd/6 ). Geralmente ambos funcionam igualmente bem. No entanto, se esse descritor de arquivo for um socket, coisas estranhas acontecem. Por exemplo:

$ 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

Aqui ls mostra que o descritor está de fato presente. Mas acessar os dados não é possível dessa maneira. Se eu usar cat <&6 , tudo funciona bem de novo.

Qual é a diferença entre as duas maneiras de acessar o descritor de arquivo?

Existe uma boa maneira de acessar um descritor se o número for dado em uma variável? ( </dev/fd/$fd funcionaria, mas <&$fd não funciona.)

(A situação acima pode ser observada no linux, mas não no OpenBSD. - Parece que o descritor de arquivo é um dispositivo de caracteres regular lá.)

    
por michas 12.01.2016 / 10:41

2 respostas

5

É assim porque a leitura de /dev/fd/ entries que representa sockets não é implementada no Linux. Você pode encontrar um bom artigo sobre raciocínio aqui . Assim, você pode chamar stat no link e é por isso que o vê com ls , mas o acesso é deliberadamente proibido.

Agora, para a segunda parte - por que o bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345 funciona? Isso é porque o soquete é lido usando a API de soquete / arquivo, não /proc filesystem. Isso é o que eu observei acontecer:

  1. A instância bash em execução no seu terminal cria um soquete com o fd 6.
  2. Criança bash é executada e chama dup2(6, 0) para anexar seu soquete como cat ' stdin .
  3. Se a dup2 call não falhar, o cat lê de stdin .

Você pode reproduzir e observar com:

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 você está se perguntando por que o processo filho bash tem acesso ao fd 6 - os descritores de arquivo sobrevivem fork e se eles não estiverem marcados para fechar em exec , eles também não serão fechados lá.

    
por 12.01.2016 / 13:29
3

Para responder à sua pergunta direta, " qual é a diferença ?":

Quando você redireciona de <&6 , o shell usa uma chamada de sistema dup2() para duplicar o descritor de arquivo. Quando você (tentar) redirecionar de </dev/fd/6 , ele usará open() .

O kernel não suporta open() em sockets em /dev/fd ; eles estão presentes apenas no diretório para informações de decoration .

    
por 12.01.2016 / 15:10