Brincando com pseudoterminais e redirecionamentos

Há uma máxima no mundo dos sistemas similares ao Unix: tudo é arquivo. Dispositivos físicos, processos ou instâncias de programas comunicam-se um com os outros através de arquivos de dispositivo ou arquivos em dispositivos referenciados em nível de execução de software em descritores de arquivos. Neste artigo ver-se-ão alguns exemplos que auxiliarão na compreensão deste princípio conforme implantado em várias distribuições Linux modernas.

[ Hits: 10.571 ]

Por: Anonimo Oculto Culto em 06/08/2018


A máxima nos sistemas Unix-similares: tudo é arquivo. Bash e os arquivos descritores



Conforme visto, os programas compatíveis com as normas que buscam compatibilizar os sistemas inspirados em Unix - as normas POSIX - possuem internamente no mínimo três ponteiros para arquivos, nomeados stdin, stdout, stderr, ponteiros para arquivos mediante os quais o programa estabelece comunicação com o mundo externo. Do arquivo referenciado em stdin o programa lê dados para processamento, e transmite dados processados escrevendo para os arquivos indicados por stdout e stderr. O canal stderr usualmente é destinado às informações relativas ao processamento, como mensagens, falhas e erros, e o canal stdout à saída de dados conforme processados. [Ref.: 20]

As instâncias de programas geralmente mantêm internamente em nível de execução uma tabela interna com uma lista de descritores de arquivos para uso, numericamente nomeados. Ao iniciar-se uma instância de programa o seu descritor 0 aponta o stdin; o descritor 1 o stdout, e o descritor 2 aponta para o destino dos dados stderr.

A fim de se poder visualizar a tabela de descritores internas à instância bash em execução mais uma vez a máxima é usada: tudo é arquivo. Cada instância do bash irá exibir os itens em sua tabela de descritores e seus respectivos apontamentos como se arquivos fossem. Tal tabela pode ser lida no diretório /dev/fd/ acessado de dentro da instância em pesquisa; usualmente uma listagem exibindo no mínimo os arquivos "0", "1" e "2" como redirecionamentos ao arquivo de dispositivo conectado. Fato importante é perceber que não se tem aqui efetivamente arquivos em disco; 0, 1 e 2 em um diretório /dev/fd/ fisicamente alocados.

Essas informações são dinamicamente produzidas pelo sistema de forma particular por cada instância do "ls" (sem redirecionamento o comando herda o conteúdo dos descritores 0, 1 e 2 do bash) em execução. Assim, abrindo-se duas janelas do konsole com suas respectivas instâncias do bash, e listando-se o diretório /dev/fd/ a partir da primeira instância com o comando:

ls -la /dev/fd/

ou preferencialmente (pois pode ocorrer pequena diferença nos resultados).

cd /dev/fd/
$ ls -la


Obtém-se [Ref.: 9 | 14 | 15 | 16 | 25]:

total 0 dr-x------ 2 lauro users 0 Jun 12 21:37 .
dr-xr-xr-x 9 lauro users 0 Jun 12 21:30 ..
lrwx------ 1 lauro users 64 Jun 12 21:37 0 -> /dev/pts/1
lrwx------ 1 lauro users 64 Jun 12 21:37 1 -> /dev/pts/1
lrwx------ 1 lauro users 64 Jun 12 21:37 2 -> /dev/pts/1
lrwx------ 1 lauro users 64 Jun 12 21:37 255 -> /dev/pts/1


E listando-se exatamente o mesmo diretório com o mesmo comando a partir da segunda instância:

dr-x------ 2 lauro users 0 Jun 12 21:37 .
dr-xr-xr-x 9 lauro users 0 Jun 12 21:30 ..
lrwx------ 1 lauro users 64 Jun 12 21:37 0 -> /dev/pts/2
lrwx------ 1 lauro users 64 Jun 12 21:37 1 -> /dev/pts/2
lrwx------ 1 lauro users 64 Jun 12 21:37 2 -> /dev/pts/2
lrwx------ 1 lauro users 64 Jun 12 21:37 255 -> /dev/pts/2


Em ambas vemos os descritores 0, 1 e 2 apontando para arquivos de dispositivos. Mas afinal, 0 aponta para /dev/pts/1 ou para /dev/pts/2?

Para o bash na primeira instância de terminal sua entrada padrão stdin conecta-se ao arquivo de dispositivo do primeiro terminal, /dev/pts/1. Já para a instância do bash invocada junto ao segundo terminal o seu descritor 0 aponta para o arquivo de dispositivo deste konsole, /dev/pts/2. Cada instância do bash recebe, e escreve, dados oriundos de seu próprio terminal.

Assim, o diretório /dev/fd/ é visto através de uma máscara diferente imposta pelo sistema para cada instância de programa em execução. Na realidade, ao ser solicitado pelo bash para busca no diretório /dev/fd/ ; o sistema encarrega-se de efetivamente disponibilizar o conteúdo do diretório também dinâmico /proc/$BASHPID/fd/ como resposta, este sim um diretório particular a cada instância mediante o número do processo (PID) da respectiva instância do programa, armazenado para cada instância do bash em uma variável de ambiente nomeada BASHPID.
FIGURA 04: cada janela do konsole possui seus próprios arquivos descritores, acessados através da listagem do diretório /dev/fd/ . Esse diretório não é fisicamente gravado em disco, e sim dinamicamente alocado, seu conteúdo sendo estritamente dependente da instância do bash (ou do programa) que o acessa. O diretório /dev/fd/ é em verdade uma ligação para /proc/self/fd/, outro diretório virtual. "self" remete ao número de processo (PID) da instância a acessar o diretório. Listando-se /proc/ vê-se grande quantidade de diretórios "numerados"; um para cada PID de instâncias de programa em execução no sistema. [Ref.: 16 | 17]

Para saber o PID de cada instância do bash em execução, a partir dela, leia o conteúdo da variável de ambiente $BASHPID com o comando echo $BASHPID . O valor retornado será diferente e particular a cada instância. [Ref.: 18 | 19 | 9]

Vale lembrar que o diretório /proc remete também a um sistema de arquivos virtual, pois ele não armazena arquivos reais em disco e sim informações do hardware, de configurações do sistema, de processos em execução na memoria, etc. Ele existe na memória volátil (RAM) do sistema, tudo criado na memória pelo Kernel do sistema operacional. Essa abstração, focada na máxima "tudo é arquivo", é conhecida como "pseudo filesystem"; ou em definição bem resumida por "sistema de arquivos de informações de processos".

Para quem quer acompanhar os detalhes, o diretório /dev/fd/ existe no pseudossistema de arquivos /dev/ como uma ligação apontando para /proc/self/fd/ . Dentro de /proc o diretório /proc/self aponta dinamicamente para um outro diretório também dentro de /proc com nome igual ao PID do processo que solicita o acesso.

Para finalizar esta seção, a listagem do diretório /dev/fd/ conforme exibida em um terminal fora do ambiente gráfico; a partir do terminal virtual acessado via CTRL-ALT-F1:

total 0 dr-x------ 2 lauro users 0 Jun 12 22:09 .
dr-xr-xr-x 9 lauro users 0 Jun 12 22:09 ..
lrwx------ 1 lauro users 64 Jun 12 22:09 0 -> /dev/tty1
lrwx------ 1 lauro users 64 Jun 12 22:09 1 -> /dev/tty1
lrwx------ 1 lauro users 64 Jun 12 22:09 2 -> /dev/tty1
lrwx------ 1 lauro users 64 Jun 12 22:09 255 -> /dev/tty1


E aqui a saída do comando ls -lad /dev/fd no terceiro terminal do konsole:

lrwxrwxrwx 1 root root 13 Jun 12 08:59 fd -> /proc/self/fd

e a saída do comando ls -lad /proc/self para o mesmo terminal:

lrwxrwxrwx 1 root root 0 Jun 12 08:59 self -> 11878

Atenção aqui que 11878 é o PID do processo "ls", e não do bash no terminal 3. Para cada execução um número de PID diferente será alocado e por tal retornado, pois uma instância diferente do ls estará em execução a cada chamada deste comando.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. A máxima nos sistemas Unix-similares: tudo é arquivo. Bash e os descritores de arquivos
   3. A máxima nos sistemas Unix-similares: tudo é arquivo. Bash e os arquivos descritores
   4. A máxima nos sistemas Unix-similares: tudo é arquivo. Arquivos descritores e redirecionamentos
   5. A máxima nos sistemas Unix-similares: tudo é arquivo. Pseudoterminais e redirecionamentos (saídas)
   6. A máxima nos sistemas Unix-similares: tudo é arquivo. Pseudoterminais e redirecionamentos (entrada)
   7. A máxima nos sistemas Unix-similares: tudo é arquivo. Referências - Comentários - Créditos às imagens
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Como programar backup com rsync e cron de maneira rápida e simples

Ubuntu 14.04 no AD com CiD

Shell Script como serviço no Windows

pam_mount e CiD - Gerenciamento centralizado dos mapeamentos de unidades de rede no Ubuntu

Piano Gripe 3 - Caracteres de controle

  
Comentários
[1] Comentário enviado por albfneto em 06/08/2018 - 14:02h

Seu artigo é ótimo, excelente. Bem escrito, muito detalhado.
favoritado,
¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
Albfneto,
Ribeirão Preto, S.P., Brasil.
Usuário Linux, Linux Counter: #479903.
Distros Favoritas: [i] Sabayon, Gentoo, OpenSUSE, Mageia e OpenMandriva[/i].

[2] Comentário enviado por anonimoculto em 06/08/2018 - 19:18h

@Albfneto: fico grato ter apreciado. À disposição.

[3] Comentário enviado por binbash em 25/08/2018 - 00:29h

Favoritei!


"Primeiro eles te ignoram, depois riem de você, depois brigam, e então você vence."
Mahatma Gandhi
http://terminalroot.com.br/shell

[4] Comentário enviado por F4xl em 18/10/2018 - 08:22h

Parabéns pelo excelente artigo! É praticamente um livro pronto!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts