Emuladores de terminal
O lado mestre substitui a linha (o par de fios TX / RX) que vai para o terminal.
O terminal exibe os caracteres que recebe em um dos fios (alguns são caracteres de controle e o fazem fazer coisas como mover o cursor, mudar de cor ...) e envia em outro fio os caracteres correspondentes às teclas digitadas.
Emuladores de terminal como o xterm não são diferentes, exceto que, em vez de enviar e receber caracteres nos fios, eles lêem e escrevem caracteres no descritor de arquivo para o lado mestre. Uma vez que eles geraram o terminal escravo, e iniciaram seu shell nisso, eles não tocam mais nisso. Além de emular o par de fios, o xterm também pode alterar algumas das propriedades da disciplina de linha por meio do descritor de arquivo para o lado mestre. Por exemplo, eles podem atualizar os atributos de tamanho para que um SIGWINCH seja enviado aos aplicativos que interagem com o escravo para notificá-los sobre um tamanho alterado.
Fora isso, há pouca inteligência no terminal / emulador de terminal.
O que você escreve em um dispositivo terminal (como o escravo pty) é o que você quer que seja exibido lá, o que você lê nele é o que você digitou lá, portanto, não faz sentido que o emulador de terminal leia ou grave nele . Eles são os que estão do outro lado.
A disciplina tty line
Uma boa parte da inteligência está na disciplina linha tty . A disciplina de linha é um módulo de software (residente no driver, no kernel) colocado em cima de um dispositivo serial / pty que fica entre esse dispositivo e a linha / fio (o lado principal de um pty).
Uma linha serial pode ter um terminal na outra extremidade, mas também um mouse ou outro computador para conexão em rede. Você pode anexar uma disciplina de linha SLIP, por exemplo, para obter uma interface de rede em cima de um dispositivo serial (ou dispositivo pty), ou pode ter uma disciplina de linha tty . A disciplina de linha tty é a disciplina de linha padrão, pelo menos no Linux, para dispositivos seriais e pty. No Linux, você pode alterar a disciplina da linha com ldattach
.
Você pode ver o efeito de desabilitar a disciplina de linha tty emitindo stty raw -echo
(observe que o prompt do bash ou outros aplicativos interativos, como vi
o terminal, definem o modo exato de que precisam, portanto, você deseja usar um aplicativo idiota que gosta cat
de experimentar isso). Então, tudo o que é gravado no dispositivo terminal escravo chega imediatamente ao lado mestre para o xterm ler, e todos os caracteres gravados pelo xterm no lado mestre ficam imediatamente disponíveis para leitura no dispositivo escravo.
A disciplina de linha é onde o editor de linha interno do dispositivo de terminal é implementado. Por exemplo, com stty icanon echo
(como é o padrão), quando você digita a
, xterm grava a
no mestre, a disciplina de linha o ecoa de volta (torna a
disponível para leitura por xterm
para exibição), mas não disponibiliza nada para leitura no lado escravo . Então, se você digita backspace, xterm envia um ^?
ou ^H
caráter, a disciplina de linha (como que ^?
ou ^H
corresponde à erase
definição de linha de disciplina) envia de volta no mestre um ^H
, space
e ^H
para xterm
apagar aa
você acabou de digitar na tela e ainda não envia nada para o aplicativo lendo do lado escravo, apenas atualiza seu buffer interno do editor de linha para remover o que a
você digitou anteriormente.
Então, quando você pressiona Enter, o xterm envia ^M
(CR), que a disciplina de linha converte na entrada para ^ ^ (LF) e envia o que você inseriu até agora para leitura no lado escravo (um aplicativo lendo /dev/pts/x
receberá o que você digitou incluindo o LF, mas não o a
desde que o excluiu); enquanto no lado mestre, ele envia um CR e LF para mover o cursor para a próxima linha e o início da tela.
A disciplina de linha também é responsável por enviar o SIGINT
sinal para o grupo de processos em primeiro plano do terminal quando recebe um ^C
caractere no lado mestre etc.
Muitos aplicativos de terminal interativos desativam a maioria dos recursos dessa disciplina de linha para implementá-los. Mas, em qualquer caso, lembre-se de que o terminal ( xterm
) tem pouco envolvimento nisso (exceto exibindo o que é solicitado para exibir).
E pode haver apenas uma sessão por processo e por dispositivo terminal. Uma sessão pode ter um terminal de controle conectado a ela, mas não é necessário (todas as sessões começam sem um terminal até abrirem um). xterm
, no processo em que você executa a execução de seu shell normalmente criará uma nova sessão (e, portanto, será desconectada do terminal de onde você iniciou xterm
), abra a nova /dev/pts/x
gerada, conectando esse dispositivo à nova sessão. Ele executará seu shell nesse processo, para que ele se torne o líder da sessão. Seu shell ou qualquer shell interativo nessa sessão normalmente faz malabarismos com grupos de processos e tcsetpgrp()
, para definir os trabalhos de primeiro e segundo plano para esse terminal.
Quanto às informações armazenadas por um dispositivo terminal com uma disciplina tty (serial ou pty) , normalmente é o que o stty
comando exibe e modifica. Toda a configuração da disciplina: tamanho da tela do terminal, local, sinalizadores de saída de entrada, configurações para caracteres especiais (como ^ C, ^ Z ...), velocidade de entrada e saída (não relevante para ptys). Isso corresponde às funções tcgetattr()
/ tcsetattr()
que no Linux são mapeadas para TCGETS
/ TCSETS
ioctls e TIOCGWINSZ
/ TIOCSWINSZ
para o tamanho da tela. Você pode argumentar que o grupo de processos atual em primeiro plano é outra informação armazenada no dispositivo terminal ( tcsetpgrp()
/ tcgetpgrp()
, TIOC{G,S}PGRP
ioctls) ou no buffer de entrada ou saída atual.
Observe que as informações de tamanho de tela armazenadas no dispositivo terminal podem não refletir a realidade. O emulador de terminal normalmente o define (através do mesmo ioctl no tamanho principal) quando sua janela é redimensionada, mas pode ficar fora de sincronia se um aplicativo chamar o ioctl no lado escravo ou quando o redimensionamento não for transmitido (no caso de uma conexão ssh que implica outro pty gerado por sshd
se ssh
ignora o, SIGWINCH
por exemplo). Alguns terminais também podem ser consultados em seu tamanho por meio de seqüências de escape, para que um aplicativo possa consultá-lo dessa maneira e atualizar a disciplina de linha com essas informações.
Para mais detalhes, você pode dar uma olhada nas páginas de manual termios
e tty_ioctl
no Debian, por exemplo.
Para jogar com outras disciplinas de linha:
Emule um mouse com um pseudo-terminal:
socat pty,link=mouse fifo:fifo
sudo inputattach -msc mouse # sets the MOUSE line discipline and specifies protocol
xinput list # see the new mouse there
exec 3<> fifo
printf '\207\12\0' >&3 # moves the cursor 10 pixels to the right
Acima, o lado mestre do pty é finalizado por socat em um pipe nomeado ( fifo
). Nós conectamos esse fifo a um processo (o shell) que grava 0x87 0x0a 0x00, o que significa no protocolo dos sistemas de mouse no button pressed, delta(x,y) = (10,0)
. Aqui, nós (o shell) não estamos emulando um terminal, mas um mouse, os 3 bytes que enviamos não devem ser lidos (potencialmente transformados) por um aplicativo do dispositivo terminal ( mouse
acima do qual é um link simbólico feito por socat
algum /dev/pts/x
dispositivo) , mas devem ser interpretados como um evento de entrada do mouse.
Crie uma interface SLIP:
# on hostA
socat tcp-listen:12345,reuseaddr pty,link=interface
# after connection from hostB:
sudo ldattach SLIP interface
ifconfig -a # see the new interface there
sudo ifconfig sl0 192.168.123.1/24
# on hostB
socat -v -x pty,link=interface tcp:hostA:12345
sudo ldattach SLIP interface
sudo ifconfig sl0 192.168.123.2/24
ping 192.168.123.1 # see the packets on socat output
Acima, o fio serial é emulado socat
como um soquete TCP entre o hostA e o hostB. A disciplina de linha SLIP interpreta os bytes trocados nessa linha virtual como pacotes IP encapsulados em SLIP para entrega na sl0
interface.