Locais de pilha de E/S

O gerente de E/S fornece a cada driver em uma cadeia de drivers em camadas um local de pilha de E/S para cada IRP configurado. Cada local de pilha de E/S consiste em uma estrutura de IO_STACK_LOCATION .

O gerenciador de E/S cria uma matriz de locais de pilha de E/S para cada IRP, com um elemento de matriz correspondente a cada driver em uma cadeia de drivers em camadas. Cada driver possui um dos locais de pilha no pacote e chama IoGetCurrentIrpStackLocation para obter informações específicas do driver sobre a operação de E/S.

Cada driver em tal cadeia é responsável por chamar IoGetNextIrpStackLocation e, em seguida, configurar o local da pilha de E/S do driver mais baixo. Qualquer local de pilha de E/S de driver de nível superior também pode ser usado para armazenar contexto sobre uma operação para que a rotina de IoCompletion do driver possa executar suas operações de limpeza.

A figura Processando IRPs em drivers em camadas mostra dois locais de pilha de E/S no IRP original porque mostra dois drivers, um driver do sistema de arquivos e um driver de dispositivo de armazenamento em massa. Os IRPs alocados pelo driver na figura de Processamento de IRPs em Drivers em Camadas não têm um local de pilha para o FSD (Driver do Sistema de Arquivos) que os criou. Qualquer driver de nível superior que aloca IRPs para drivers de nível inferior também determina quantos locais de pilha de E/S os novos IRPs devem ter, de acordo com o valor StackSize do objeto de dispositivo do driver mais baixo.

A figura a seguir mostra o conteúdo do IRP em mais detalhes.

diagrama ilustrando o conteúdo do local da pilha de e/s em uma irp.

Conforme mostrado na figura, cada local de pilha de E/S específica do driver em um IRP contém as seguintes informações gerais:

  • O código de função principal (IRP_MJ_XXX), indicando a operação básica que o driver deve executar

  • Para alguns códigos de função principais tratados por FSDs, drivers SCSI de nível superior e todos os drivers PnP, um código de função secundária (IRP_MN_XXX), indicando qual subcase da operação básica o driver deve realizar

  • Um conjunto de argumentos específicos da operação, como o comprimento e o local inicial de um buffer no qual ou do qual o driver transfere dados

  • Um ponteiro para o objeto de dispositivo criado pelo driver, representando o dispositivo de destino (físico, lógico ou virtual) para a operação solicitada

  • Um ponteiro para o objeto de arquivo, representando um arquivo aberto, dispositivo, diretório ou volume

    Um driver do sistema de arquivos acessa o objeto de arquivo por meio de seu local de pilha de E/S em IRPs. Outros drivers geralmente ignoram o objeto de arquivo.

O conjunto de códigos de função principal e secundária do IRP que um determinado driver manipula pode ser específico do tipo de dispositivo. No entanto, drivers de nível mais baixo e drivers intermediários (incluindo drivers de função PnP e filtro) geralmente lidam com o seguinte conjunto de solicitações básicas:

  • IRP_MJ_CREATE – abra o objeto de dispositivo de destino, indicando que ele está presente e disponível para operações de E/S

  • IRP_MJ_READ — transferir dados do dispositivo

  • IRP_MJ_WRITE — transferir dados para o dispositivo

  • IRP_MJ_DEVICE_CONTROL — configurar (ou redefinir) o dispositivo, de acordo com um IOCTL (código de controle de E/S) específico do tipo de dispositivo definido pelo sistema

  • IRP_MJ_CLOSE – fechar o objeto de dispositivo de destino

  • IRP_MJ_PNP – execute uma operação de Plug and Play no dispositivo. Uma solicitação IRP_MJ_PNP é enviada pelo gerente PnP por meio do gerente de E/S.

  • IRP_MJ_POWER – execute uma operação de energia no dispositivo. Uma solicitação de IRP_MJ_POWER é enviada pelo power manager por meio do gerente de E/S.

Para obter mais informações sobre os principais códigos de função IRP que os drivers são necessários para lidar, consulte Códigos de função principais do IRP.

Em geral, o gerente de E/S envia IRPs com pelo menos dois locais de pilha de E/S para drivers de dispositivo de armazenamento em massa porque um sistema de arquivos está em camadas sobre outros drivers para dispositivos de armazenamento em massa. O gerente de E/S envia IRPs com um único local de pilha para qualquer driver que não tenha nenhum outro driver em camadas acima dele.

No entanto, o gerente de E/S fornece suporte para adicionar um novo driver a qualquer cadeia de drivers existentes no sistema. Por exemplo, um driver espelho intermediário que faz backup de dados em uma determinada partição de disco pode ser inserido entre um par de drivers, como o driver do sistema de arquivos e o driver de nível mais baixo mostrados na figura Processando IRPs em drivers em camadas . Quando esse novo driver se anexa à pilha do dispositivo, o gerenciador de E/S ajusta o número de locais de pilha de E/S em todos os IRPs enviados ao sistema de arquivos, espelho e drivers de nível mais baixo. Cada IRP que o sistema de arquivos na figura processando IRPs em drivers em camadas alocada também conteria outro local de pilha de E/S para um novo driver espelho.

Observe que esse suporte para adicionar novos drivers a uma cadeia existente implica certas restrições ao acesso de qualquer driver específico aos locais de pilha de E/S em IRPs:

  • Um driver de nível superior em uma cadeia de drivers em camadas pode acessar com segurança apenas os próprios locais de pilha de E/S do próximo driver de nível inferior em qualquer IRP. Esse driver deve configurar o local da pilha de E/S para o próximo driver de nível inferior em IRPs. No entanto, ao criar um driver de nível mais alto, você não pode prever quando (ou se) um novo driver será adicionado à cadeia existente logo abaixo do driver.

    Portanto, você deve assumir que qualquer driver adicionado posteriormente manipulará os mesmos códigos de função principais do IRP (IRP_MJ_XXX) que o driver de nível inferior deslocado.

  • O driver de nível mais baixo em uma cadeia de drivers em camadas pode acessar com segurança apenas seu próprio local de pilha de E/S em qualquer IRP. Ao criar esse driver, você não pode prever quando (ou se) um novo driver será adicionado à cadeia existente acima do driver do dispositivo.

    Ao criar um driver de nível mais baixo, suponha que o driver possa continuar a processar IRPs usando as informações passadas em seu próprio local de pilha de E/S, qualquer que seja a fonte de origem de um determinado IRP e, no entanto, muitos drivers estão em camadas acima dele.