Como uma interrupção é tratada no Linux?


35

Eu só sei que isso Interrupté hardware signal assertioncausado em um pino de processador. Mas eu gostaria de saber como o Linux OS lida com isso.
Quais são as coisas que acontecem quando ocorre uma interrupção?


tldp.org/LDP/tlk/dd/interrupts.html explica tudo sobre a pergunta que você fez #
John

Respostas:


40

Aqui está uma visão de alto nível do processamento de baixo nível. Estou descrevendo uma arquitetura típica simples, arquiteturas reais podem ser mais complexas ou diferem de maneiras que não importam nesse nível de detalhe.

Quando ocorre uma interrupção , o processador verifica se as interrupções estão mascaradas. Se estiverem, nada acontece até serem desmascarados. Quando as interrupções se tornam desmascaradas, se houver alguma interrupção pendente, o processador escolhe uma.

Em seguida, o processador executa a interrupção ramificando para um endereço específico na memória. O código nesse endereço é chamado de manipulador de interrupção . Quando o processador ramifica lá, oculta as interrupções (para que o manipulador de interrupções tenha controle exclusivo) e salva o conteúdo de alguns registros em algum lugar (normalmente outros registros).

O manipulador de interrupção faz o que deve fazer, normalmente comunicando-se com o periférico que acionou a interrupção para enviar ou receber dados. Se a interrupção foi disparada pelo timer, o manipulador pode acionar o agendador do SO, para alternar para um encadeamento diferente. Quando o manipulador termina a execução, ele executa uma instrução especial de retorno de interrupção que restaura os registradores salvos e desmascara as interrupções.

O manipulador de interrupções deve ser executado rapidamente, porque está impedindo a execução de qualquer outra interrupção. No kernel Linux, o processamento de interrupção é dividido em duas partes:

  • A "metade superior" é o manipulador de interrupções. Ele faz o mínimo necessário, normalmente se comunica com o hardware e define um sinalizador em algum lugar na memória do kernel.
  • A “metade inferior” faz qualquer outro processamento necessário, por exemplo, copiar dados na memória do processo, atualizar estruturas de dados do kernel, etc. Isso pode levar algum tempo e até bloquear a espera por outra parte do sistema, uma vez que é executado com as interrupções ativadas.

Como de costume neste tópico, para obter mais informações, leia Linux Device Drivers ; o capítulo 10 é sobre interrupções.


22

Gilles já descreveu o caso geral de uma interrupção; o seguinte se aplica especificamente ao Linux 2.6 em uma arquitetura Intel (parte disso também é baseada nas especificações da Intel).

Uma interrupção é um evento que altera a sequência de instruções executadas pelo processador.
Existem dois tipos diferentes de interrupções:

  • Interrupção síncrona (exceção) produzida pela CPU durante o processamento de instruções
  • Interrupção assíncrona (interrupção) emitida por outros dispositivos de hardware

As exceções são causadas por erros de programação (fe Erro de divisão , Falha na página , Estouro ) que devem ser tratados pelo kernel. Ele envia um sinal para o programa e tenta se recuperar do erro.

As duas exceções a seguir são classificadas:

  • Exceção detectada pelo processador gerada pela CPU ao detectar uma condição anômala; dividido em três grupos: Falhas geralmente podem ser corrigidas, Traps relatam uma execução, Abortos são erros graves.
  • Exceção programada solicitada pelo programador, manipulada como uma armadilha.

As interrupções podem ser emitidas por dispositivos de E / S (teclado, adaptador de rede, ..), temporizadores de intervalo e (em sistemas multiprocessadores) outras CPUs. Quando ocorre uma interrupção, a CPU deve parar sua instrução atual e executar a interrupção recém-chegada. Ele precisa salvar o antigo estado de processo interrompido para (provavelmente) retomá-lo após a interrupção ser tratada.

Lidar com interrupções é uma tarefa delicada:

  • As interrupções podem ocorrer a qualquer momento, o kernel tenta tirá-lo do caminho o mais rápido possível
  • Uma interrupção pode ser interrompida por outra interrupção
  • Existem regiões no kernel que não devem ser interrompidas.

Dois níveis diferentes de interrupção são definidos:

  • Interrupções mascaráveis emitidas por dispositivos de E / S; pode estar em dois estados, mascarado ou não. Somente interrupções não mascaradas estão sendo processadas.
  • Interrupções não mascaráveis ; avarias críticas (falha de hardware fe); sempre processado pela CPU.

Todo dispositivo de hardware possui sua própria linha de solicitação de interrupção (IRQ). Os IRQs são numerados a partir de 0. Todas as linhas de IRQ são conectadas a um PIC (Programmable Interrupt Controller). O PIC escuta os IRQs e os atribui à CPU. Também é possível desativar uma linha de IRQ específica.
Os sistemas modernos de multiprocessamento Linux geralmente incluem o Advanced PIC (APIC) mais recente, que distribui solicitações de IRQ igualmente entre as CPUs.

A etapa intermediária entre uma interrupção ou exceção e seu tratamento é a Tabela de Descritor de Interrupção (IDT). Esta tabela associa cada vetor de interrupção ou exceção (um número) a um manipulador especificado (fe Erro de divisão é tratado pela função divide_error()).

Por meio do IDT, o kernel sabe exatamente como lidar com a interrupção ou exceção ocorrida.


Então, o que o kernel quando ocorre uma interrupção?

  • A CPU verifica após cada instrução se há um IRQ do (A) PIC
  • Nesse caso, consulte o IDT para mapear o vetor recebido para uma função
  • Verifica se a interrupção foi emitida por uma fonte autorizada
  • Salva os registros do processo interrompido
  • Chame a função correspondente para lidar com a interrupção
  • Carregue os registros salvos recentemente do processo interrompido e tente retomar

Você pode esclarecer "A CPU verifica após cada instrução se há um IRQ do (A) PIC" . Como exatamente isso acontece? VIPEstá relacionado com -flag in flags register ou o que seja? Obrigado antecipadamente
red0ct

7

Primeiro, todos os participantes envolvidos no tratamento de interrupções são dispositivos de hardware periféricos, controlador de interrupção, CPU, kernel do sistema operacional e drivers. Os dispositivos periféricos de hardware são responsáveis ​​pela geração de interrupções. Eles afirmam as linhas de solicitação de interrupção quando querem atenção do kernel do sistema operacional. Esses sinais são multiplexados pelo controlador de interrupção, responsável pela coleta de sinais de interrupção. Também é responsável pela determinação da ordem na qual os sinais de interrupção serão transmitidos para a CPU. O controlador de interrupção é capaz de desativar temporariamente a linha de solicitação de interrupção específica (IRQL) e reativá-la novamente (máscara de IRQL). O controlador de interrupção passa solicitações de interrupção coletadas para a CPU sequencialmente. CPU após a conclusão da execução de cada instrução A CPU verifica se há pedidos de interrupção em espera do controlador de interrupção. Se a CPU constatar que há uma solicitação de espera E o sinalizador de interrupção ativada estiver definido no registro de controle interno da CPU, a CPU iniciará o tratamento de interrupções. Como você pode ver, manipulando o sinalizador Interrupção na CPU e comunicando-se com o controlador de interrupção, o kernel do Linux é capaz de controlar a aceitação da interrupção. Por exemplo, o Linux pode desativar a aceitação de interrupções de um dispositivo específico ou desativar a aceitação de interrupções. O kernel do Linux é capaz de controlar a aceitação da interrupção. Por exemplo, o Linux pode desativar a aceitação de interrupções de um dispositivo específico ou desativar a aceitação de interrupções. O kernel do Linux é capaz de controlar a aceitação da interrupção. Por exemplo, o Linux pode desativar a aceitação de interrupções de um dispositivo específico ou desativar a aceitação de interrupções.

O que acontece quando o processador recebe uma solicitação de interrupção? Em primeiro lugar, a CPU desativa automaticamente as interrupções, redefinindo o sinalizador de interrupção. Eles serão reativados assim que a manipulação de interrupção for concluída. Ao mesmo tempo, a CPU faz uma quantidade mínima de trabalho necessária para alternar a CPU do modo de usuário para o modo de kernel, de maneira que permita retomar a execução do código interrompido. A CPU consulta com estruturas especiais de controle de CPU preenchidas pelo kernel do Linux para encontrar um endereço de código para o qual o controle será passado. Este endereço é o endereço da primeira instrução do manipulador de interrupções, que faz parte do kernel do Linux.

Como uma primeira etapa do manuseio de interrupções, o kernel identifica o vetor de interrupção recebida para identificar que tipo de evento aconteceu no sistema. O vetor de interrupção define quais ações o Linux executará para lidar com isso. Como uma segunda etapa, o Linux salva o restante dos registros da CPU (que não foram salvos pela CPU automaticamente) e que potencialmente podem ser usados ​​pelo programa interrompido. Essa é uma ação muito importante, pois permite que o Linux manipule interrupções de forma transparente, em relação ao programa interrompido. Como uma terceira etapa, o Linux realiza a alternância para o modo kernel, definindo o ambiente do kernel e o estado da CPU necessário para isso. E, finalmente, o manipulador de interrupção dependente de vetor é chamado. (Você pode procurar na macro BUILD_INTERRUPT3 em arch \ x86 \ kernel \ entry_32. S para obter detalhes adicionais do exemplo relacionado à arquitetura x86) No caso de dispositivos periféricos, essa é uma rotina do_IRQ (). (Veja o arch \ x86 \ kernel \ irq.c)

O manipulador de interrupção dependente de vetor geralmente encapsulado por chamadas para irq_enter () e irq_exit (). A área de código entre um par dessas funções é atômica em relação a outras áreas e também é atômica em relação a pares de cli / sti. Irq_enter () e irq_exit () também capturam algumas estatísticas relacionadas ao tratamento de interrupções. Finalmente, o kernel examina a tabela vector_irq para encontrar o número irq atribuído ao vetor da interrupção recebida e chamar handle_irq () (de arch \ x86 \ kernel \ irq_32.c).

Nesse ponto, a parte comum do tratamento de interrupções no Linux termina, porque o kernel verifica a rotina do manipulador de interrupções dependente de dispositivo instalada pelo driver de dispositivo como parte do descritor irq e a invoca. Se esse manipulador não foi instalado pelo driver, o kernel apenas reconhece a interrupção no controlador de interrupção e sai do manipulador de interrupção geral.

Após o final da interrupção, o kernel restaura o estado do programa que foi interrompido anteriormente e retoma a execução do programa.


CPU consults with special CPU control structures filled by Linux kernel to find an address of code to which control will be passed.Sim! Eu me pergunto o que essas estruturas de controle especiais são embora ...
autômato

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.