Compartir a través de


Procesamiento de IRP en un controlador de Lowest-Level

Los controladores físicos de nivel más bajo tienen ciertas rutinas estándar que los controladores de nivel superior no necesitan. El conjunto de rutinas estándar para los controladores de nivel más bajo también varía según los siguientes criterios:

  • La naturaleza del dispositivo que controla cada controlador

  • Si el controlador configura sus objetos de dispositivo para E/S directa o almacenada en búfer

  • El diseño del controlador individual

Para ilustrar los roles de las rutinas de controlador estándar, en la ilustración siguiente se muestra la ruta de acceso que un IRP de ejemplo puede tomar tal como lo procesa un controlador de dispositivo de almacenamiento masivo de nivel más bajo. El controlador de la ilustración tiene las siguientes características:

  • El dispositivo genera interrupciones al final de cada operación de E/S, por lo que este controlador tiene rutinas ISR y DpcForIsr .

  • El controlador tiene una rutina StartIo , en lugar de configurar colas internas para IRP y administrar su propia cola.

  • El controlador usa DMA del sistema, por lo que establece las marcas de sus objetos de dispositivo para la E/S directa y tiene una rutina AdapterControl .

diagrama que ilustra una ruta de acceso de irp a través de rutinas de controlador de nivel inferior.

Como se muestra en esta ilustración, el administrador de E/S crea un IRP y lo envía a la rutina de distribución del controlador para el código de función principal especificado. Suponiendo que el código de función es IRP_MJ_READ o IRP_MJ_WRITE, la rutina de distribución es DDDispatchReadWrite.

Llamada a IoGetCurrentIrpStackLocation

Cualquier rutina de controlador que requiera parámetros IRP debe llamar a IoGetCurrentIrpStackLocation para obtener la ubicación de la pila de E/S del controlador. Estas rutinas incluyen rutinas de envío que controlan más de un código de función de E/S principal (IRP_MJ_*XXX), controlan una función que admite funciones secundarias (IRP_MN_XXX) o controlan las solicitudes de control de E/S del dispositivo (*IRP_MJ_DEVICE_CONTROL o IRP_MJ_INTERNAL_DEVICE_CONTROL), junto con todas las demás rutinas de controlador que procesan un IRP.

La ubicación de pila de E/S de este controlador es la más baja, con un número indefinido de ubicaciones de pila de E/S de controladores de nivel superior que se muestran sombreadas. Para simplificar, las llamadas a IoGetCurrentIrpStackLocation de las rutinas DispatchReadWrite, StartIo, AdapterControl y DpcForIsr no se muestran en la ilustración anterior.

Llamada a IoMarkIrpPending e IoStartPacket

El controlador de ejemplo no completa el IRP en su rutina de envío, sino que procesa el IRP en su rutina StartIo . Antes de poder hacerlo, la rutina de envío llama a IoMarkIrpPending para indicar que el IRP aún no se ha completado. A continuación, llama a IoStartPacket para poner en cola el IRP para su posterior procesamiento mediante la rutina StartIo del controlador. La rutina de distribución también devuelve el valor NTSTATUS STATUS_PENDING.

En la ilustración siguiente se muestra la llamada a IoStartPacket.

diagrama que ilustra una llamada a iostartpacket.

Si el controlador está ocupado procesando otro IRP en el dispositivo, IoStartPacket inserta el IRP en la cola de dispositivos asociada al objeto de dispositivo. Opcionalmente, el controlador puede proporcionar un valor de clave como parámetro a IoStartPacket para imponer un orden determinado por el controlador en los IRP de la cola del dispositivo.

Si el controlador no está ocupado y la cola del dispositivo está vacía, el administrador de E/S llama inmediatamente a su rutina StartIo , pasando el IRP de entrada.

En el caso de los dispositivos de almacenamiento masivo, el controlador de nivel más bajo no necesita proporcionar una rutina Cancel cuando llama a IoStartPacket por dos motivos:

  1. Un sistema de archivos superado por este tipo de controlador normalmente controla la cancelación de las solicitudes de E/S de archivos.

  2. Los controladores de dispositivos de almacenamiento masivo procesan los IRP rápidamente.

Normalmente, el controlador de nivel más alto de una cadena de controladores en capas controla la cancelación de los IRP.

Llamar a AllocateAdapterChannel y MapTransfer

Suponiendo que la rutina StartIo , que se muestra en la ilustración que ilustra una ruta irP a través de rutinas de controlador de nivel inferior, determina que la solicitud de transferencia se puede realizar mediante una sola operación DMA, la rutina StartIo llama a AllocateAdapterChannel con el punto de entrada de la rutina AdapterControl del controlador y irP.

Cuando el controlador DMA del sistema está disponible, el administrador de E/S llama a la rutina AdapterControl del controlador para configurar la operación de transferencia. La rutina AdapterControl llama a MapTransfer para configurar el controlador DMA del sistema. A continuación, el controlador programa su dispositivo para la operación DMA y devuelve. (Para obtener más información sobre el uso de objetos DMA y adaptadores, vea Técnicas de entrada y salida).

Llamada a IoRequestDpc desde el ISR del controlador

Cuando se interrumpe el dispositivo para indicar que se ha completado su operación de transferencia, el ISR del controlador impide que el dispositivo genere interrupciones y llame a IoRequestDpc, como se muestra en la ilustración que ilustra una ruta de acceso IRP a través de rutinas de controlador de nivel inferior.

Esta llamada pone en cola la rutina DpcForIsr del controlador para completar la mayor parte de la operación de transferencia posible en una prioridad de hardware inferior (IRQL).

Llamada a IoStartNextPacket e IoCompleteRequest

Cuando la rutina DpcForIsr ha terminado de procesar la transferencia, llama a IoStartNextPacket rápidamente para que se llame a la rutina StartIo del controlador con el siguiente IRP en la cola del dispositivo, si hay alguna en cola. La rutina DpcForIsr también establece el bloque de estado de E/S de IRP just-completed y, a continuación, llama a IoCompleteRequest para irP.

En la ilustración siguiente se muestran las llamadas de este controlador a IoStartNextPacket y IoCompleteRequest.

llamar a iostartnextpacket e iocompleterequest.

Los controladores deben llamar a IoStartNextPacket o IoStartNextPacketByKey para comenzar la siguiente operación de E/S solicitada lo antes posible, preferiblemente antes de llamar a IoCompleteRequest.

Si hay irP en cola para el dispositivo, IoStartNextPacket llama a KeRemoveDeviceQueue para quitar el siguiente IRP de la cola. A continuación, el administrador de E/S llama a la rutina StartIo del controlador, pasando el IRP en cola. Si no hay IRP actualmente en la cola de dispositivos, IoStartNextPacket simplemente vuelve al autor de la llamada.

Establecer el bloque de estado de E/S en un IRP

Cada controlador de nivel más bajo debe establecer el bloque de estado de E /S de IRP antes de llamar a IoCompleteRequest. (En la ilustración anterior, el segundo área sombreada denota el bloque de estado). El bloque de estado de E/S proporciona información a los controladores de nivel superior y, en última instancia, al solicitante original de la operación de E/S. Cualquier controlador de nivel superior por encima del controlador de la ilustración anterior podría haber configurado una rutina de IoCompletion que lea el bloque de estado de E/S establecido por este controlador. Normalmente, los controladores de nivel superior no modifican el bloque de estado de E/S en un IRP completado por un controlador de dispositivo, a menos que el controlador de nivel superior vuelva a intentar irP, en cuyo caso reinicializa el bloque de estado de E/S.

Cada controlador de nivel superior que completa un IRP sin enviarlo al siguiente controlador inferior también debe establecer el bloque de estado de E/S en ese IRP antes de llamar a IoCompleteRequest. Para un buen rendimiento general de E/S, un controlador de nivel superior debe comprobar los parámetros en su propia ubicación de pila de E/S de cada IRP y, si los parámetros no son válidos, debe establecer el bloque de estado de E/S y completar la propia solicitud. Siempre que sea posible, un controlador debe evitar pasar una solicitud no válida en para reducir los controladores de la cadena.

Suponiendo que la operación de transferencia de la ilustración anterior se realiza correctamente, la rutina DpcForIsr , que se muestra en la ilustración que ilustra una ruta de acceso irP a través de rutinas de controlador de nivel inferior, establece STATUS_SUCCESS en Estado y el número de bytes transferidos en Información para el bloque de estado de E/S de IRP.

Muchas de las rutinas de controlador estándar también devuelven valores de tipo NTSTATUS. Para obtener más información sobre las constantes NTSTATUS como STATUS_SUCCESS, consulte Registro de errores.