Partilhar via


Always Preemptible e Always Interruptible

O objetivo do design preemptível e interruptível do sistema operacional é maximizar o desempenho do sistema. Qualquer thread pode ser preempído por um thread com prioridade mais alta, e qualquer ISR (rotina de serviço de interrupção) de qualquer driver pode ser interrompida por uma rotina que é executada em um nível de solicitação de interrupção mais alto (IRQL).

O componente kernel determina quando uma sequência de código é executada, de acordo com um destes critérios de priorização:

  • O esquema de prioridade de tempo de execução definido pelo kernel para threads.

    Cada thread no sistema tem um atributo de prioridade associado. Em geral, a maioria dos threads tem atributos de prioridade variável : eles são sempre preempíveis e estão agendados para executar round robin com todos os outros threads que estão atualmente no mesmo nível de prioridade. Alguns threads têm atributos de prioridade em tempo real : esses threads críticos de tempo são executados até a conclusão, a menos que sejam precedidos por um thread que tenha um atributo de prioridade em tempo real mais alto. A arquitetura do Microsoft Windows não fornece um sistema inerentemente em tempo real.

    Seja qual for seu atributo de prioridade, qualquer thread no sistema pode ser preempcionado quando ocorrem interrupções de hardware e certos tipos de interrupções de software.

  • O IRQL ( nível de solicitação de interrupção ) definido pelo kernel ao qual um vetor de interrupção específico é atribuído em uma determinada plataforma.

    O kernel prioriza interrupções de hardware e software para que algum código de modo kernel, incluindo a maioria dos drivers, seja executado em IRQLs mais altas, fazendo com que ele tenha uma prioridade de agendamento maior do que outros threads no sistema. O IRQL específico no qual uma parte do código de driver do modo kernel é executada é determinada pela prioridade de hardware de seu dispositivo subjacente.

    O código do modo kernel é sempre interruptível: uma interrupção com um valor IRQL mais alto pode ocorrer a qualquer momento, fazendo com que outra parte do código do modo kernel que tenha um IRQL atribuído ao sistema mais alto seja executada imediatamente nesse processador. No entanto, quando um trecho de código é executado em um determinado IRQL, o kernel mascara todos os vetores de interrupção com um valor IRQL menor ou igual no processador.

O nível irql mais baixo é chamado de PASSIVE_LEVEL. Nesse nível, nenhum vetor de interrupção é mascarado. Os threads geralmente são executados em IRQL=PASSIVE_LEVEL. Os próximos níveis mais altos de IRQL são para interrupções de software. Esses níveis incluem APC_LEVEL, DISPATCH_LEVEL ou, para depuração de kernel, WAKE_LEVEL. As interrupções do dispositivo ainda têm valores IRQL mais altos. O kernel reserva os valores IRQL mais altos para interrupções críticas do sistema, como aquelas do relógio do sistema ou erros de barramento.

Algumas rotinas de suporte do sistema são executadas em IRQL=PASSIVE_LEVEL, porque são implementadas como código paginável ou acessam dados pagináveis ou porque alguns componentes do modo kernel configuram seus próprios threads.

Da mesma forma, algumas rotinas de driver padrão geralmente são executadas em IRQL=PASSIVE_LEVEL. No entanto, várias rotinas de driver padrão são executadas em IRQL=DISPATCH_LEVEL ou, para um driver de nível mais baixo, no IRQL do dispositivo (também chamado de DIRQL). Para obter mais informações sobre IRQLs, consulte Gerenciando prioridades de hardware.

Cada rotina em um driver é interruptível. Isso inclui qualquer rotina em execução em um IRQL maior do que PASSIVE_LEVEL. Qualquer rotina em execução em um IRQL específico retém o controle do processador somente se nenhuma interrupção para um IRQL mais alto ocorrer enquanto essa rotina estiver em execução.

Ao contrário dos drivers em alguns sistemas operacionais de computador pessoal mais antigos, o ISR de um driver do Microsoft Windows nunca é uma rotina grande e complexa que faz a maior parte do processamento de E/S do driver. Isso ocorre porque qualquer ISR ( rotina de serviço de interrupção ) de qualquer driver pode ser interrompida por outra rotina (por exemplo, pelo ISR de outro driver) que é executada em um IRQL mais alto. Assim, o ISR do driver não retém necessariamente o controle de uma CPU, ininterruptamente, desde o início de seu caminho de execução até o final.

Em drivers do Windows, um ISR normalmente salva informações de estado de hardware, enfileira uma DPC ( chamada de procedimento adiado ) e, em seguida, sai rapidamente. Posteriormente, o sistema removerá o DPC do driver para que o driver possa concluir operações de E/S em um IRQL inferior (DISPATCH_LEVEL). Para um bom desempenho geral do sistema, todas as rotinas executadas em ALTOS IRQLs devem abrir mão do controle da CPU rapidamente.

No Windows, todos os threads têm um contexto de thread. Esse contexto consiste em informações que identificam o processo que possui o thread, além de outras características, como os direitos de acesso do thread.

Em geral, apenas um driver de nível mais alto é chamado no contexto do thread que está solicitando a operação de E/S atual do driver. Um driver de nível intermediário ou de nível mais baixo nunca pode assumir que está em execução no contexto do thread que solicitou sua operação de E/S atual.

Consequentemente, as rotinas de driver geralmente são executadas em um contexto de thread arbitrário — o contexto de qualquer thread atual quando uma rotina de driver padrão é chamada. Por motivos de desempenho (para evitar comutadores de contexto), pouquíssimos drivers configuram seus próprios threads.