Para controlar entrada e saída de dados, não é interessante que a CPU tenha que ficar continuamente monitorando e status de dispositivos como discos ou teclados. O mecanismo de interrupções permite que o hardware "chame a atenção" da CPU quando há algo a ser feito.
Interrupções geradas por algum dispositivo externo à CPU, como teclado ou controlador de disco, são chamadas de interrupções de hardware ou assíncronas (ocorrem independentemente das instruções que a CPU está executando.
Quando ocorre uma interrupção, a CPU interrompe o processamento do programa em execução e executa um pedaço de código (tipicamente parte do sistema operacional) chamado de tratador de interrupção. Em muitos casos, após a execução do tratador, a CPU volta a executar o programa interrompido.
---------------------------------------------------------------------- exec. de prog. P | exec. do tratador de interrupção| retomada de P | | ---------------------------------------------------------------------- ^ | interrupção
Observe que, em termos de fluxo de controle, a execução do tratador é um pouco como uma chamada de rotina. No entanto, a chamada de rotina é iniciada por instruções do programa em execução, e o tratador de interrupção assíncrona não. Por isso, não há nenhuma comunicação entre o programa interrompido e o tratador (parâmetros ou retorno)!
Um tipo importante de interrupção de hardware á a interrupção do relógio. Em particular, esse mecanismo permite ao sistema operacional atribuir quotas de tempos de execução (fatias de tempo) para cada um dos processos em um sistema multiprograma. A cada interrupção do relógio, o tratador pode verificar se a fatia de tempo do processo em execução já se esgotou e, se for esse o caso, suspendê-lo e acionar o escalonador para que esse escolha outro processo para colocar em execução.
Um outro tipo de interrupção são as interrupções síncronas, muitas vezes também chamadas de traps. Traps ocorrem em consequência da instrução sendo executada.
Algumas são geradas pelo hardware, para indicar por exemplo overflow em operações aritméticas ou acesso a regiões de memória não permitidas. Essas são situações em que o programa não teria como prosseguir. O hardware sinaliza uma interrupção para passar o controle para uma parte do sistema operacional (o tratador da interrupção em questão), que tipicamente termina a execução do programa.
Traps também podem ser geradas explicitamente por instruções do programa. Essa é uma forma do programa acionar o sistema operacional, por exemplo para requisitar um serviço de entrada ou saída. Um programa não pode "chamar" uma rotina do sistema operacional, já que o sistema operacional é um processo a parte, com seu próprio espaço de endereçamento. Através do mecanismo de interrupção de software, um processo qualquer pode ativar um tratador que pode "encaminhar" uma chamada ao sistema operacional.
Traps também são usadas em situações onde o programa não tem como prosseguir pois aconteceu uma exceção como overflow aritmético, tentativa de acesso a endereço inválido ou estouro da pilha.
Como as interrupções síncronas ocorrem em função da instrução que está sendo executada, nesse caso é até possível o programa passar algum parâmetro para o tratador. Isso ocorre com frequencia no caso de interrupções usadas para chamar o sistema operacional.
Tipicamente, o hardware detecta que ocorreu uma interrupção, aguarda o final da execução da instrução corrente e aciona o tratador, antes salvando o contexto de execução so processo interrompido. Para que a execução do processo possa ser reiniciada mais tarde, é necessário salvar o program counter e outros registradores de status. Os registradores com dados do programa devem ser salvos pelo próprio tratador (ou seja, por software) caso ele os utilize.
Em muitas arquiteturas, existe uma pilha independente associada ao tratamento de interrupções.
int n
do assembly IA-32 gera um trap.
Historicamente, chamadas ao sistema são feitas com int $0x80
.
No Linux, antes de se executar essa instrução,
o número da chamada (ou seja, a definição do serviço a ser executado)
deve ser colocado no registrador %eax
, e os argumentos
nos registradores %ebx
, %ecx
, %edx
,
%esi
e %edi
.
Depois que o sistema operacional executa o serviço requisitado,
o controle retorna à instrução seguinte a int
,
com o valor de retorno em %eax
.