Como a entrada do teclado e a saída de texto funcionam?

85

Suponha que eu pressione a Atecla em um editor de texto e isso insira o caractere ano documento e o exiba na tela. Sei que o aplicativo editor não está se comunicando diretamente com o hardware (há um kernel e outras coisas), então o que está acontecendo dentro do meu computador?

Gilles
fonte

Respostas:

100

Existem vários cenários diferentes; Vou descrever os mais comuns. Os sucessivos eventos macroscópicos são:

  1. Entrada: o evento de pressionamento de tecla é transmitido do hardware do teclado para o aplicativo.
  2. Processando: o aplicativo decide que, como a tecla Afoi pressionada, deve exibir o caractere a.
  3. Saída: o aplicativo dá a ordem para exibição ana tela.

Aplicações GUI

A interface gráfica de usuário padrão de fato de sistemas unix é o X Window System , geralmente chamado de X11, porque estabilizou na 11ª versão de seu protocolo principal entre aplicativos e o servidor de exibição. Um programa chamado servidor X fica entre o kernel do sistema operacional e os aplicativos; fornece serviços, incluindo a exibição de janelas na tela e a transmissão de pressionamentos de teclas para a janela que está em foco.

Entrada

+----------+              +-------------+         +-----+
| keyboard |------------->| motherboard |-------->| CPU |
+----------+              +-------------+         +-----+
             USB, PS/2, …                 PCI, …
             key down/up

Primeiro, as informações sobre o pressionamento e liberação das teclas são transmitidas do teclado para o computador e dentro do computador. Os detalhes dependem do tipo de hardware. Não vou me debruçar mais sobre essa parte porque as informações permanecem as mesmas ao longo desta parte da cadeia: uma certa tecla foi pressionada ou liberada.

         +--------+        +----------+          +-------------+
-------->| kernel |------->| X server |--------->| application |
         +--------+        +----------+          +-------------+
interrupt          scancode             keysym
                   =keycode            +modifiers

Quando um evento de hardware acontece, a CPU aciona uma interrupção , o que faz com que algum código no kernel seja executado. Esse código detecta que o evento de hardware é um pressionamento ou liberação de tecla proveniente de um teclado e registra o código de verificação que identifica a tecla.

O servidor X lê eventos de entrada através de um arquivo de dispositivo , por exemplo, /dev/input/eventNNNno Linux (onde NNN é um número). Sempre que há um evento, o kernel sinaliza que há dados para ler nesse dispositivo. O arquivo do dispositivo transmite os principais eventos de up / down com um código de verificação, que pode ou não ser idêntico ao valor transmitido pelo hardware (o kernel pode converter o código de verificação de um valor dependente do teclado para um valor comum, e o Linux não retransmitir os códigos de verificação que ele não conhece ).

X chama o código de verificação que lê um código de chave . O servidor X mantém uma tabela que traduz códigos de chave em academias de teclas (abreviação de "símbolo de chave"). Keycodes são numéricos, enquanto keysyms estão nomes como A, aacute, F1, KP_Add, Control_L, ... O keysym podem ser diferentes dependendo de qual teclas modificadoras são pressionadas ( Shift, Ctrl...).

Existem dois mecanismos para configurar o mapeamento de códigos de chave para academias de chaves:

  • O xmodmap é o mecanismo tradicional. É uma tabela simples de mapeamento de códigos de chave para uma lista de key-clubs (não modificados, deslocados, ...).
  • O XKB é um mecanismo mais poderoso, porém mais complexo, com melhor suporte para mais modificadores, em particular para configuração em dois idiomas, entre outros.

Os aplicativos se conectam ao servidor X e recebem uma notificação quando uma tecla é pressionada enquanto uma janela desse aplicativo está em foco. A notificação indica que um certo tom de tecla foi pressionado ou liberado, bem como quais modificadores estão pressionados no momento. Você pode ver as principais academias executando o programa a xevpartir de um terminal. O que o aplicativo faz com as informações depende dele; alguns aplicativos possuem ligações de teclas configuráveis.

Em uma configuração típica, quando você pressiona a tecla rotulada Asem modificadores, isso envia o teclado apara o aplicativo; se o aplicativo estiver no modo em que você está digitando texto, isso insere o caractere a.

A relação do layout do teclado e o xmodmap entra em mais detalhes na entrada do teclado. Como os eventos do mouse funcionam no linux? fornece uma visão geral da entrada do mouse nos níveis mais baixos.

Resultado

+-------------+        +----------+          +-----+         +---------+
| application |------->| X server |---····-->| GPU |-------->| monitor |
+-------------+        +----------+          +-----+         +---------+
               text or              varies          VGA, DVI,
               image                                HDMI, …

Existem duas maneiras de exibir um personagem.

Consulte Quais são os propósitos dos diferentes tipos de fontes XWindows? para uma discussão sobre a renderização de texto do lado do cliente e do servidor no X11.

O que acontece entre o servidor X e a Unidade de processamento gráfico (o processador na placa de vídeo) depende muito do hardware. Sistemas simples têm o servidor X desenhado em uma região de memória chamada framebuffer , que a GPU seleciona para exibição. Sistemas avançados, como os encontrados em qualquer PC ou smartphone do século 21, permitem que a GPU realize algumas operações diretamente para obter melhor desempenho. Por fim, a GPU transmite o conteúdo da tela pixel por pixel a cada fração de segundo para o monitor.

Aplicativo em modo de texto, executando em um terminal

Se o seu editor de texto for um aplicativo em modo de texto em execução em um terminal, é o terminal que é o aplicativo para os fins da seção acima. Nesta seção, explico a interface entre o aplicativo em modo texto e o terminal. Primeiro, descrevo o caso de um emulador de terminal executando o X11. Qual é a diferença exata entre um 'terminal', um 'shell', um 'tty' e um 'console'? pode ser um contexto útil aqui. Depois de ler isso, você pode ler o muito mais detalhado Quais são as responsabilidades de cada componente do Pseudo-Terminal (PTY) (software, lado mestre, lado escravo)?

Entrada

      +-------------------+               +-------------+
----->| terminal emulator |-------------->| application |
      +-------------------+               +-------------+
keysym                     character or
                           escape sequence

O emulador de terminal recebe eventos como " Leftfoi pressionado enquanto Shiftestava inativo". A interface entre o emulador de terminal e o aplicativo de modo texto é um pseudo-terminal (pty) , um dispositivo de caracteres que transmite bytes. Quando o emulador de terminal recebe um evento de pressionamento de tecla, ele o transforma em um ou mais bytes, que o aplicativo obtém para ler no dispositivo pty.

Os caracteres imprimíveis fora do intervalo ASCII são transmitidos como um ou mais bytes, dependendo do caractere e da codificação . Por exemplo, na codificação UTF-8 do conjunto de caracteres Unicode , os caracteres no intervalo ASCII são codificados como um único bytes, enquanto os caracteres fora desse intervalo são codificados como vários bytes.

As teclas pressionadas que correspondem a uma tecla de função ou a um caracter imprimível com modificadores como Ctrlou Altsão enviadas como uma sequência de escape . As seqüências de escape geralmente consistem no escape de caracteres (valor de byte 27 = 0x1B = \033, às vezes representado como ^[ou \e) seguido por um ou mais caracteres imprimíveis. Algumas teclas ou combinações de teclas têm um caractere de controle correspondente a elas nas codificações baseadas em ASCII (que são praticamente todas usadas atualmente, incluindo Unicode): Ctrl+ lettergera um valor de caractere no intervalo de 1 a 26, Escé o caractere de escape visto acima e também é o mesmo que Ctrl+ [, Tabé o mesmo que Ctrl+ I,Returné o mesmo que Ctrl+ M, etc.

Terminais diferentes enviam sequências de escape diferentes para uma determinada tecla ou combinação de teclas. Felizmente, o inverso não é verdadeiro: dada uma sequência, na prática há no máximo uma combinação de teclas que ele codifica. A única exceção é o caractere 127 = 0x7f =, \0177que é frequentemente, Backspacemas às vezes Delete.

Em um terminal, se você digitar Ctrl+ Vseguido de uma combinação de teclas, isso inserirá o primeiro byte da sequência de escape da combinação de teclas literalmente. Como as seqüências de escape normalmente consistem apenas em caracteres imprimíveis após o primeiro, isso insere toda a sequência de escape literalmente. Veja a tabela de atalhos de teclas? para uma discussão sobre o zsh neste contexto.

O terminal pode transmitir a mesma sequência de escape para algumas combinações de modificadores (por exemplo, muitos terminais transmitem um caractere de espaço para ambos Spacee Shift+ Space; xterm possui um modo de distinguir combinações de modificadores, mas os terminais baseados na popular biblioteca vte não ). Algumas teclas não são transmitidas, por exemplo, teclas modificadoras ou teclas que acionam uma ligação do emulador de terminal (por exemplo, um comando copiar ou colar).

Cabe ao aplicativo converter seqüências de escape em nomes de chave simbólicos, se assim o desejar.

Resultado

+-------------+               +-------------------+
| application |-------------->| terminal emulator |--->
+-------------+               +-------------------+
               character or
               escape sequence

A saída é bastante mais simples que a entrada. Se o aplicativo enviar um caractere para o arquivo do dispositivo pty, o emulador de terminal o exibirá na posição atual do cursor. (O emulador de terminal mantém uma posição do cursor e rola se o cursor cair sob a parte inferior da tela.) O aplicativo também pode gerar seqüências de escape (principalmente começando com ^[ou ^]) para instruir o terminal a executar ações como mover o cursor, alterar os atributos do texto (cor, negrito,…) ou apagar parte da tela.

As seqüências de escape suportadas pelo emulador de terminal são descritas no banco de dados termcap ou terminfo . Atualmente, a maioria dos emuladores de terminal está alinhada com o xterm . Consulte a documentação sobre variáveis ​​LESS_TERMCAP_ *? para uma discussão mais longa dos bancos de dados de informações sobre a capacidade do terminal e Como parar o cursor de piscar e Posso definir as cores dos terminais da minha máquina local para usar as cores da máquina em que ssh? para alguns exemplos de uso.

Aplicativo em execução em um console de texto

Se o aplicativo estiver sendo executado diretamente em um console de texto, ou seja, um terminal fornecido pelo kernel e não por um aplicativo emulador de terminal, os mesmos princípios se aplicam. A interface entre o terminal e o aplicativo ainda é um fluxo de bytes que transmite caracteres, com teclas e comandos especiais codificados como seqüências de escape.

Aplicativo remoto, acessado pela rede

Aplicativo de texto remoto

Se você executar um programa em uma máquina remota, por exemplo, através de SSH , o protocolo de comunicação de rede retransmitirá os dados no nível pty.

+-------------+           +------+           +-----+           +----------+
| application |<--------->| sshd |<--------->| ssh |<--------->| terminal |
+-------------+           +------+           +-----+           +----------+
               byte stream        byte stream       byte stream
               (char/seq)         over TCP/…        (char/seq)

Isso é principalmente transparente, exceto que às vezes o banco de dados do terminal remoto pode não conhecer todos os recursos do terminal local.

Aplicativo remoto X11

O protocolo de comunicação entre aplicativos e o servidor é um fluxo de bytes que pode ser enviado por um protocolo de rede como o SSH.

+-------------+            +------+        +-----+            +----------+
| application |<---------->| sshd |<------>| ssh |<---------->| X server |
+-------------+            +------+        +-----+            +----------+
               X11 protocol        X11 over       X11 protocol
                                   TCP/…

Isso é quase sempre transparente, exceto que alguns recursos de aceleração, como decodificação de filme e renderização em 3D, que requerem comunicação direta entre o aplicativo e a exibição, não estão disponíveis.

Gilles
fonte
Não tenho certeza absoluta, mas como a resposta geralmente é bastante detalhada, pergunto-me se a parte que diz "Aplicativo em execução em um console de texto" pode não ter recursos de que coisas como man 5 keymapssão usadas para traduzir o keycodespara scancodes. Embora, como mencionado, seja essencialmente semelhante, ainda existe um conjunto totalmente diferente de ferramentas / programas, e isso talvez mereça mais algumas idéias. Além disso, a resposta é +1 e ótima por causa das perguntas relacionadas incorporadas.
humanityANDpeace
Eu encontrei PgUpe Ctrl+PgUpsou indistinguível em tty1 (TERM = linux). O mapeamento de sequência keysym -> control pode ser configurado?
stewbasic
@stewbasic Sim, com um mapa de teclado carregado por loadkeys. Procure por perguntas com a tag linux console keyboard-layout .
Gilles
@Gilles thanks! Vale a pena notar que loadkeys altera ambos os mapeamentos keycode -> keysym e keysym -> sequência de escape (isso não foi inicialmente óbvio para mim).
stewbasic
11
Uau, essa deve ser uma das melhores respostas que eu já vi no Stackexchange - bem organizada, responde à pergunta, fornece contexto relevante, faz referências cruzadas de outras respostas úteis e até possui arte ASCII legal!
Johntron
4

Se você quiser ver isso em um sistema Unix que seja pequeno o suficiente para ser compreensível, ao Xv6 . É mais ou menos o mítico Unix 6ª Edição que se tornou a base do famoso comentário de John Lion , que circulou por muito tempo como samizdat. Seu código foi reformulado para compilar sob ANSI C e levando em consideração os desenvolvimentos modernos, como multiprocessadores.

vonbrand
fonte