
No Linux, um Terminal está associado a um Shell. O Terminal envia a entrada para o Shell (por exemplo: pwd
), e o Shell envia a saída de volta para o Terminal (por exemplo: /home/paul
).
Este diagrama mostra o relacionamento entre um Terminal e um Shell (suponha que o Terminal que estou usando seja gnome-terminal
e o Shell seja bash
):
Agora o que quero saber é qual mecanismo o Terminal e o Shell usam para trocar dados. Isto é o que eu acho que acontece:
- Quando
gnome-terminal
executado, ele criará um arquivo representando uma porta serial no/dev/pts
diretório (digamos que o nome do arquivo seja/dev/pts/0
). gnome-terminal
executará então o Shell associado a ele (por exemplo:bash
) e passará a ele o nome do arquivo pts (o nome do arquivo pts pode ser passado através dos argumentos da linha de comando, por exemplo).- Agora ambos
gnome-terminal
ebash
começariam a ler a partir de/dev/pts/0
. - Quando
gnome-terminal
quiser enviar dados parabash
, ele gravaria esses dados/dev/pts/0
ebash
leria esses dados/dev/pts/0
. - Quando
bash
quiser enviar dados paragnome-terminal
, ele gravaria esses dados/dev/pts/0
eand
gnome-terminal
leria esses dados/dev/pts/0
.
Este diagrama mostra o que acabei de explicar:
Estou correto em meu entendimento?
Observação: é claro que o arquivo pts poderia ser um arquivo tty se estivéssemos usando terminais virtuais (ou seja, quando não estivéssemos usando uma GUI), mas a lógica ainda seria a mesma.
Responder1
Está faltando uma peça necessária. Dispositivos pseudo-tty não são simétricos como os soquetes. Existe uma extremidade mestre e uma extremidade escrava. Os arquivos /dev/pts
representam os dispositivos escravos.
O emulador de terminal cria um pseudo-tty chamando openpty
(ou forkpty
o que é openpty
mais alguma configuração bônus para o caso comum em que você deseja executar um novo processo em seu novo tty). Em um nível inferior, isso envolve abrir /dev/ptmx
e fazer alguns ioctls mágicos.
Como resultado da chamada, openpty
o emulador de terminal obtém um par de descritores de arquivo, e também pode obter o nome do arquivo /dev/pts
correspondente ao escravo. O mestre não recebe um nome individual porque nunca há necessidade de um processo filho abri-lo pelo nome.
Os dispositivos mestre e escravo agem como extremidades opostas de um soquete: o que você escreve em uma extremidade é lido na outra. Mas como este é um tty, todos os modos tty são aplicados aos dados no caminho.
Por exemplo, se você for um emulador de terminal e receber um pressionamento de Atecla, deverá gravar 'a'
no descritor de arquivo mestre. Isso é diretamente equivalente a enviar esse byte pela linha serial do terminal para o computador. Isso resultará na 'a'
leitura do escravo (por qualquer programa que o esteja lendo - por exemplo, o shell).
Se você receber um pressionamento de Dtecla enquanto a Ctrltecla estiver pressionada, você deverá escrever um 4
byte ( 'D' ^ 0x40
) no descritor de arquivo mestre. (Porque é isso que um terminal real envia pelo fio.) O que acontece a seguir depende do modo tty. No modo bruto, o programa que lê o escravo tty verá um 4
byte. No modo cozido, o tty ativará o comportamento "Tecla especial EOF pressionada".
Na direção inversa, também ocorre algum processamento. Quando algum programa grava '\n'
no escravo tty, você provavelmente receberá "\r\n"
no mestre o descritor de arquivo, por causa do onlcr
pós-processamento.
Seção de histórico, pule se estiver entediado
Há muito tempo, os dispositivos escravos tinham nomes como /dev/ttyp0
e cada um tinha um mestre correspondente, como /dev/ptyp0
. Eles não foram criados dinamicamente. Um emulador de terminal poderia simplesmente sondar todos eles para encontrar um que não esteja em uso e começar a usá-lo. Gerenciar propriedade e permissões era um problema. xterm
foi setuid-root apenas para poder chown o escravo.
O novo esquema, chamado "UNIX98 ptys", lida com a criação e propriedade de dispositivos por meio de ioctls mágicos, de modo que os arquivos só aparecem quando /dev/pts
estão em uso e pertencem ao usuário que executou o programa que os criou.