Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Qualquer driver pode usar um objeto semáforo para sincronizar operações entre seus threads criados pelo driver e outras rotinas de driver. Por exemplo, um thread dedicado ao driver pode se colocar em um estado de espera quando não há solicitações de E/S pendentes para o driver, e as rotinas de despacho do driver podem definir o semáforo para o estado Sinalizado logo após enfileirar um IRP.
As rotinas de despacho dos drivers de nível mais alto, que são executadas no contexto do thread que solicita uma operação de E/S, podem usar um semáforo para proteger um recurso compartilhado entre as rotinas de despacho. As rotinas de despacho de driver de nível inferior para operações de E/S síncronas também podem usar um semáforo para proteger um recurso compartilhado entre esse subconjunto de rotinas de despacho ou com um thread criado pelo driver.
Qualquer driver que use um objeto semáforo deve chamar KeInitializeSemaphore antes de esperar ou liberar o semáforo. A figura a seguir ilustra como um driver com um thread pode usar um objeto semáforo.
Como mostra a figura anterior, esse driver deve fornecer o armazenamento para o objeto semáforo, que deve ser residente. O driver pode usar a extensão de dispositivo de um objeto de dispositivo criado pelo driver, a extensão do controlador se ele usar um objeto de controlador ou pool não paginado alocado pelo driver.
Quando o do driver AddDevice chamadas de rotina KeInitializeSemaphore, ele deve passar um ponteiro para o armazenamento residente do driver para o objeto semáforo. Além disso, o chamador deve especificar um de contagem de para o objeto semáforo, como mostrado na figura anterior, que determina seu estado inicial (diferente de zero para Sinalizado).
O chamador também deve especificar um de Limite de para o semáforo, que pode ser um dos seguintes:
Limite = 1
Quando esse semáforo é definido para o estado Sinalizado, um único thread aguardando que o semáforo seja definido para o estado Sinalizado torna-se elegível para execução e pode acessar qualquer recurso protegido pelo semáforo.
Este tipo de semáforo também é chamado de semáforo binário porque um fio tem ou não acesso exclusivo ao recurso protegido por semáforo.
Limite > 1
Quando esse semáforo é definido para o estado Sinalizado, algum número de threads aguardando que o objeto semáforo seja definido para o estado Sinalizado tornam-se elegíveis para execução e podem acessar qualquer recurso protegido pelo semáforo.
Esse tipo de semáforo é chamado de de semáforo de contagem de porque a rotina que define o semáforo para o estado Sinalizado também especifica quantos fios de espera podem ter seus estados alterados de espera para pronto. O número desses threads de espera pode ser o Limit definido quando o semáforo foi inicializado ou algum número menor do que essa predefinição Limit.
Poucos drivers de dispositivo ou intermediários têm um único thread criado por driver; ainda menos têm um conjunto de fios que podem esperar que um semáforo seja adquirido ou libertado. Poucos drivers fornecidos pelo sistema usam objetos semáforos e, dos que o fazem, ainda menos usam um semáforo binário. Embora um semáforo binário possa parecer ser semelhante em funcionalidade a um objeto mutex , um semáforo binário não fornece a proteção interna contra bloqueios que um objeto mutex tem para threads do sistema em execução em máquinas SMP.
Depois que um driver com um semáforo inicializado é carregado, ele pode sincronizar operações no semáforo que protege um recurso compartilhado. Por exemplo, um driver com um thread dedicado ao dispositivo que gerencia o enfileiramento de IRPs, como o driver do controlador de disquete do sistema, pode sincronizar o enfileiramento de IRP em um semáforo, como mostrado na figura anterior:
O thread chama KeWaitForSingleObject com um ponteiro para o armazenamento fornecido pelo driver para que o objeto semáforo inicializado se coloque em um estado de espera.
Começam a entrar IRPs que exigem operações de E/S do dispositivo. As rotinas de despacho do motorista inserem cada um desses IRP em uma fila intertravada sob controle de bloqueio de rotação e chamam KeReleaseSemaphore com um ponteiro para o objeto semáforo, um impulso de prioridade determinado pelo driver para o thread (Increment, como mostrado na figura anterior), um de Ajuste de de 1 que é adicionado à Contagem do semáforo à medida que cada IRP é enfileirado, e um Boolean Wait definido para FALSE. Uma contagem de semáforos diferente de zero define o objeto semáforo para o estado Sinalizado, alterando assim o estado do thread de espera para pronto.
O kernel despacha o thread para execução assim que um processador está disponível: ou seja, nenhum outro thread com uma prioridade mais alta está atualmente no estado pronto e não há rotinas de modo kernel para serem executadas em um IRQL mais alto.
O thread remove um IRP da fila intertravada sob controle spin-lock, passa-o para outras rotinas de driver para processamento adicional e chama KeWaitForSingleObject novamente. Se o semáforo ainda estiver definido para o estado Signaled (ou seja, sua Count permanecerá diferente de zero, indicando que mais IRPs estão na fila intertravada do driver), o kernel novamente alterará o estado do thread de aguardando para pronto.
Usando um semáforo de contagem dessa maneira, esse thread de driver "sabe" que há um IRP a ser removido da fila intertravada sempre que esse thread for executado.
Para obter informações específicas para gerenciar IRQL ao chamar KeReleaseSemaphore , consulte a seção Comentários do KeReleaseSemaphore.
Qualquer rotina de driver padrão que seja executada em um IRQL maior que PASSIVE_LEVEL não pode esperar por um intervalo diferente de zero em qualquer objeto do dispatcher sem derrubar o sistema; consulte Kernel Dispatcher Objects para obter detalhes. No entanto, essa rotina pode chamar KeReleaseSemaphore enquanto estiver sendo executado em um IRQL menor ou igual a DISPATCH_LEVEL.
Para obter um resumo dos IRQLs nos quais as rotinas de driver padrão são executadas, consulte Gerenciando prioridades de hardware. Para obter os requisitos de IRQL de uma rotina de suporte específica, consulte a página de referência da rotina.