Por que não consigo ler / dev / stdout com um editor de texto?

9

Comecei a aprender como o Everything Is A File TM no Linux, o que me fez pensar no que aconteceria se eu lesse literalmente em / dev / stdout:

$ cat /dev/stdout 
^C
$ tail /dev/stdout 
^C

( ^CSou eu que estou matando o programa depois de travar).

Quando tento vim, recebo a mensagem impensável: "/ dev / stdout" não é um arquivo. Suspiro!

Então, o que dá, por que estou recebendo interrupções ou mensagens de erro quando tento ler esses "arquivos"?

user1717828
fonte
1
O que o vim considera um arquivo e o que se entende por "tudo é um arquivo" (nenhuma marca comercial associada) no * nix não são a mesma coisa. Veja, por exemplo, nº 1 e nº 2 .
goldilocks

Respostas:

11

por que estou tendo problemas

Você não está recebendo "hangups" de cat(1)e tail(1)eles estão apenas bloqueando a leitura. cat(1)aguarda a entrada e a imprime assim que vê uma linha completa:

$ cat /dev/stdout
foo
foo
bar
bar

Aqui eu digitei fooEnterbarEnterCTRL- D.

tail(1)aguarda a entrada e a imprime somente quando pode detectar EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Aqui eu digitei novamente fooEnterbarEnterCTRL- D.

ou mensagens de erro

O Vim é o único que fornece um erro. Faz isso porque corre stat(2) contra /dev/stdoute descobre que não tem o S_IFREGbit definido.

/dev/stdouté um arquivo, mas não um arquivo regular . De fato, há alguma dança no kernel para dar uma entrada no sistema de arquivos. No Linux:

$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May  8 19:42 /dev/stdout -> /proc/self/fd/1

No OpenBSD:

$ ls -l /dev/stdout
crw-rw-rw-  1 root  wheel   22,   1 May  7 09:05:03 2015 /dev/stdout

No FreeBSD:

$ ls -l /dev/stdout
lrwxr-xr-x  1 root  wheel  4 May  8 21:35 /dev/stdout -> fd/1

$ ls -l /dev/fd/1
crw-rw-rw-  1 root  wheel  0x18 May  8 21:35 /dev/fd/1
lcd047
fonte
5

(Quase) tudo é um arquivo, mas nem tudo é um arquivo regular . Não faz sentido chamar um editor de texto em algo que seja um arquivo especial, como diretório, soquete de rede, porta serial etc.

O arquivo /dev/stdoutpode ser uma das várias coisas, dependendo da variante unix:

  • um arquivo "especial", normalmente um dispositivo de caractere;
  • um link simbólico “mágico” que aponta para o arquivo que o processo que o acessou abriu neste descritor;
  • um link simbólico para um dos itens acima.

De qualquer forma, a abertura de /dev/stdoutarquivos e similares cria um novo descritor de arquivo associado ao mesmo arquivo que o aplicativo já abriu no descritor de arquivo 1. “Saída padrão” significa o descritor de arquivo 1, e é apenas uma convenção que esse descritor de arquivo seja usado para saída - o kernel não se importa.

Quando você executa um programa em um terminal, todos os três descritores padrão (0 = entrada padrão, 1 = saída padrão, 2 = erro padrão) são abertos no dispositivo do terminal. A leitura desse dispositivo retorna caracteres digitados pelo usuário e a gravação nesse dispositivo exibe texto na janela do terminal. (Não existe uma maneira padrão, dado um dispositivo terminal, de ler a saída que ele exibe ou injetar entrada nele.)

Quando você executa cat /dev/stdout, faz exatamente a mesma coisa que cat /dev/stdinou cat /dev/stderr, porque esses três descritores de arquivos estão conectados ao mesmo arquivo: ele diz catpara ler no terminal. Isso é o que catsem argumentos também.

Se você executou cat /dev/stdout >foo, /dev/stdoutconsulte o arquivo foo- esse comando é equivalente cat foo >foo. Dependendo da catimplementação, pode ocorrer um erro (a versão GNU reclama que “arquivo de entrada é arquivo de saída”) ou pode não fazer nada porque lê o arquivo fooque está vazio ( >fooapenas o truncou). Com uma versão catque não detecta esse caso especial, se foonão estiver vazio, cat /dev/stdout >>fooo equivalente cat foo >>fooao arquivo anexa o conteúdo do arquivo indefinidamente.

Quando você executa vim /dev/stdout, ele reclama porque não sabe editar um terminal (isso simplesmente não faz sentido).

Gilles 'SO- parar de ser mau'
fonte
2

cate tailprocura conteúdo opcional seguido pelo final do arquivo. /dev/stdoutpermanece aberto cate tailcontinue procurando.

Politank-Z
fonte