A maneira mais fácil de entender os dispositivos terminais Linux ( /dev/tty*
, /dev/pts/*
) é como você pensa neles como streaming sockets . Como se o /dev/tty12
fosse uma porta TCP, como 127.0.0.1:8080
.
Os processos estão conectando-os, obtêm informações deles, escrevem neles e, finalmente, os desconectam. Um soquete (terminal) pode ter uma conexão com vários processos.
Outros processos podem escutá-los , eles são tipicamente os programas de emulador de terminal, mas nem sempre. No caso dos terminais de caracteres, o próprio kernel Linux funciona como um "daemon ouvinte" no dispositivo terminal.
O "recurso extra" que um terminal tem, mas um socket não tem: o kernel controla quais processos estão conectando-o, e é capaz de sinalizá-los sobre a necessidade . Então acontece, por exemplo, se você pressionar ctrl / c.
Uma lista detalhada dos sinais passados que você pode ler em esta resposta.
O que exatamente acontece se você pressionar ctrl / c?
Não é se alguém pressionar um botão normal, por exemplo, uma tecla "a". Nesse caso, a tecla pressionada é simplesmente gravada no dispositivo terminal e pode ser lida pelos processos que leem a partir dela (o que geralmente é o processo em primeiro plano).
No caso de um pressionamento de tecla tão extraordinário, por exemplo, ctrl / z, ou você fecha / redimensiona a janela do terminal, e assim por diante, o terminal obtém o pedido e o kernel envia para todos os processos anexados o sinal correspondente . Para todos eles, será importante mais tarde.
Esses dispositivos também podem ser controlados por chamadas ioctl()
bem direcionadas.
Se o bash executar um subprocesso (ou seja, um comando externo), ocorrerá o seguinte:
- bash inicia o processo em segundo plano, dando a ele o terminal
- o bash pára de receber entrada do terminal
- depois que o processo parar, o bash define tudo de volta.
No entanto, o bash permanece conectado ao dispositivo terminal e, se um ctrl / c estiver chegando, ele receberá o sinal. Além disso, o comando externo receberá o sinal.
No entanto, esses sinais podem ser substituídos ( signal()
, sigaction()
system calls). O Bash substitui-os, isto é, substitui a rotina padrão de manipulação de sinais (que simplesmente a interrompe) por sua própria. É por isso que não sai se você pressionar ctrl / c em um prompt de comando.
No entanto, um sleep 60
será encerrado. Não altera seus manipuladores de sinais.
Se você executar um comando interno bash, este manipulador de sinal funcionará como você disse (ele interrompe a execução do comando interno e o leva de volta ao prompt).