2012/10/21

O que são os Interrupts (e o Polling)?


No outro dia, ao falar da tecla Escape e da forma como "interrompia" o processamento dos computadores (noutros tempos), disse que vos iria falar dos interrupts a nível do hardware. Se bem se lembram, o processamento feito por um CPU, embora envolva coisas altamente complexas, é na sua essência algo bastante básico.

Basicamente, o CPU executa uma instrução, incrementa o registo para apontar à instrução seguinte, e assim sucessivamente - num ciclo infinito que nunca pára (mesmo quando o PC não está a fazer "nada", está sempre a executar algum pedaço de código que lhe diz... não faças nada, não faças nada, não faças nada.)
Em programação seria algo como:
  1. Não fazer nada
  2. Regressar ao passo 1

Inevitavelmente, os CPUs necessitam de interagir com os demais componentes que constituem um "computador": quer sejam eles um disco rígido, ou um simples teclado.

Imaginem então, que tinham que saber se um utilizador tinha carregado numa tecla. Quais seriam as forma de o fazer? A mais simples e básica seria perguntar ao teclado se alguém tinha carregado numa tecla: fazendo com que o nosso programa anterior de "não fazer nada" passasse a ser algo como:
  1. verificar se alguém carregou numa tecla
  2. se sim, mostrar a tecla no ecrã
  3. se não, voltar ao passo 1
O "problema" é que um programa de computador será algo que se espera que faça "algo", e que portanto estará a fazer algum qualquer tipo de processamento complicado e útil para uma qualquer determinada função. Então... como ficaria o nosso teclado?

Novamente, há várias hipóteses de o fazer: por exemplo, poderíamos fazê-lo a espaços regulares no nosso código:
  1. fazer uma parte processamento complicado
  2. verificar se alguém carregou numa tecla
  3. fazer mais um bocado de processamento complicado
  4. verificar se alguém carregou numa tecla
  5. etc.

Uma solução que não é lá muito elegante... e que tem também muitas desvantagens: imagine-se que uma pessoa carregava numa tecla num momento em que o CPU estava a fazer parte do outro processamento? Não seria detectada pelo sistema, e causaria enorme frustração nos utilizadores. (E também nos programadores, que teriam que espalhar pelo seu programa centenas ou milhares de verificações para o teclado). Para além de que, caso se tratasse de um qualquer outro sistema onde os dados recebido (por exemplo, por uma porta série) tivessem obrigatoriamente que ser recebido no exacto momento em que chegam, ou seriam perdidos para sempre... não nos podiamos dar ao luxo de apenas ir espreitar a porta de X em X tempo.

Não seria mais simples ter um qualquer outro sistema que nos permitisse saber automaticamente quando algo acontecesse, sem que tivessemos que estar continuamente a verificar se tal aconteceu ou não?

E ísso mesmo que são os Interrupts! 

(E já agora, a tal técnica de estar a verificar "manualmente" se algo aconteceu, como fizemos antes, é o tal sistema designado por "polling").


Como podem ver na imagem no início deste post, os Interrupts são gerados por linhas específicas que existem nos CPUs e microprocessadores e que permitem interromper o funcionamento normal do processador.


Ou seja, quando algum desses interrupts ocorre, o CPU pára a execução do que está a fazer, e salta para um bloco que permite executar outro bloco de código especial, e regressando ao processamento normal assim que terminar.

Isto funciona a nível do próprio hardware do CPU, e como tal, evita que se desperdicem recursos continuamente perguntando "Já se carregou numa tecla? Já se carregou numa tecla? etc."

Desta forma poderíamos dividir o nosso problema de forma mais eficiente em:
  1. fazer o processamento
  2. no final, verificar se carregaram numa tecla
Mas agora acompanhado por um bloco de código "interrupt" que faria:
  1. guarda a tecla carregada num buffer temporário para verificar mais tarde

Assim, mesmo durante o processamento do programa principal, toda e cada tecla que fosse carregada iria sendo guardado num espaço de memória temporário, e quando o processamento chegasse ao final, poderíamos saber tudo aquilo que aconteceu, sem ter perdido nenhuma informação.

E até o tal caso da tecla ESCAPE, que permitiria fazer no bloco de processamento do interrupt algo como: se a tecla carregada foi a tecla de ESCAPE, então aborta o processamento do programa principal, e regressa ao menu principal do sistema operativo (por exemplo).


Uma forma simples de o descrever: o sistema de polling é o equivalente a ter uma criança no banco de trás de um automóvel a perguntar continuamente "já chegamos?" durante uma viagem. O sistema de interrupts será equivalente a ter a criança a brincar distraidamente no banco de trás, até que alguém lhe diga "já chegamos!"


Assim podemos garantir que, o que quer que o CPU esteja a fazer, podemos sempre garantir que não deixa passar despercebido qualquer acontecimento externo que necessite da sua atenção imediata: quer seja uma tecla, ou um bloco de dados que está pronto para ser lido do disco rígido, ou qualquer outra coisa.

Como é normal neste tipo de coisas, esta explicação simplificada esconde mecanismos bastante mais complexos que permitem controlar estes interrupts. Os interrupts podem ter vários níveis e prioridades, de forma a que se possam ignorar - se se desejar - interrupts que não sejam considerados essenciais ou críticos durante certo tipo de processamentos; há interrupts por hardware e por software; há interrupts "ininterruptíveis" que são impossíveis de bloquear, etc. etc. Mas, no geral, espero que tenham ficado elucidados quanto a este sistema que habitualmente fica escondido no interior dos "computadores", mas que é essencial para o seu eficaz funcionamento.

1 comentário:

  1. É por isto que gosto de vir a este blog. Parabéns pelo artigo.

    ResponderEliminar