Partilhar via


Configurando e usando filas interbloqueadas

Novos drivers devem usar a estrutura de fila IRP segura para cancelamento em preferência aos métodos descritos nesta seção.

Drivers com threads dedicados ao dispositivo ou drivers que usam threads de trabalho executivo, como a maioria dos FSDs do sistema, são os tipos mais prováveis de drivers para gerenciar seu próprio enfileiramento interno de tempo de execução de IRPs em uma fila intertravada. Todos os drivers PnP, incluindo os drivers WDM, também devem enfileirar determinados IRPs internamente enquanto fazem transições de estado de energia e de PnP.

Normalmente, esses drivers configuram uma fila intertravada duplamente vinculada; cada IRP contém um membro do tipo LIST_ENTRY, que um driver pode usar para vincular duplamente os IRPs que ele está mantendo atualmente. Um driver não pode enfileirar novamente IRPs para novas tentativas se configurar uma fila interbloqueada vinculada individualmente.

Um driver deve configurar a sua fila interbloqueada na inicialização do dispositivo. A figura a seguir ilustra uma fila duplamente ligada e entrelaçada, as rotinas de suporte que um driver deve chamar para configurar nesta fila, e um conjunto de rotinas ExInterlockedXxx que um driver pode chamar para inserir IRPs e remover IRPs da fila.

Diagrama que ilustra uma fila bloqueada.

Como mostra esta figura, um driver deve fornecer o armazenamento para a própria fila e para o seguinte, a fim de configurar uma fila intertravada duplamente vinculada:

  • Um bloqueio de rotação executivo, que o driver deve invocar KeInitializeSpinLock para inicializar. Normalmente, um driver inicializa o bloqueio de rotação quando configura a(s) extensão(ões) do dispositivo para o(s) seu(s) objeto(s) de dispositivo em sua rotina AddDevice .

  • O cabeçalho da lista para a fila, que o driver deve inicializar chamando InitializeListHead.

A maioria dos drivers que usam filas duplamente encadeadas e interbloqueadas fornecem o armazenamento necessário na extensão de dispositivo de um objeto de dispositivo criado pelo driver. Em vez disso, a fila e o bloqueio de rotação executivo podem estar em uma extensão de controlador (se o driver usar um objeto de controlador) ou em pool não paginado alocado pelo driver.

Enquanto o driver está aceitando solicitações de E/S, ele pode inserir um IRP em sua fila chamando uma das seguintes rotinas de suporte se o ListHead for do tipo LIST_ENTRY, conforme mostrado na figura anterior:

ExInterlockedInsertTailList para colocar o IRP no final da fila

ExInterlockedInsertHeadList para colocar o IRP na frente da fila. Os motoristas geralmente chamam essa rotina apenas quando precisam repetir uma solicitação específica.

O driver deve passar ponteiros para o IRP (ListEntry), bem como os ponteiros ListHead e o executive spin lock (Lock) que foram previamente inicializados, para cada uma destas rotinas ExInterlockedInsertXxxList. Somente ponteiros para ListHead e Lock são necessários quando o driver desfila um IRP chamando ExInterlockedRemoveHeadList. Para prevenir bloqueios, o controlador não deve estar segurando um ExecutiveSpinLock que seja passado para qualquer rotina ExInterlockedXxx.

Uma vez que uma fila intertravada é protegida pelo spin lock executivo, o driver pode inserir IRPs na sua fila duplamente vinculada e removê-los de forma segura com vários processadores de qualquer rotina de driver executada com um nível de IRQL menor ou igual a IRQL = DISPATCH_LEVEL.

Uma fila com um ListHead do tipo LIST_ENTRY, como mostrado na figura anterior, é uma lista duplamente vinculada. Um com um ListHead do tipo SLIST_HEADER é uma lista sequenciada e vinculada individualmente. Um driver inicializa o ListHead para uma fila intertravada sequenciada ligada individualmente chamando ExInitializeSListHead.

Um driver que nunca tenta operações de E/S novamente pode usar ExInterlockedPushEntrySList e ExInterlockedPopEntrySList para gerenciar seu enfileiramento de IRPs internamente em uma fila intertravada sequenciada e vinculada individualmente. Qualquer driver que use esse tipo de fila intertravada também deve fornecer armazenamento residente para um ListHead do tipo SLIST_HEADER e para um ExecutiveSpinLock, conforme mostrado na figura anterior. Ele deve inicializar o bloqueio de rotação e configurar sua fila antes de chamar ExInterlockedPushEntrySList para inserir a entrada inicial em sua fila.

Para obter mais informações, consulte Gerenciando prioridades de hardware e bloqueios de rotação. Para obter os requisitos de IRQL para uma rotina de suporte específica, consulte a página de referência da rotina.