Compartir a través de


Restricciones en rutinas de distribución

Nota:

Para obtener una confiabilidad y un rendimiento óptimos, use controladores de minifiltro del sistema de archivos con compatibilidad con el Administrador de filtros de archivos en lugar de controladores de filtro del sistema de archivos heredados. Para migrar el controlador heredado a un controlador de minifiltro, consulte Directrices para portar controladores de filtro heredados.

En las instrucciones siguientes se describe brevemente cómo los controladores de filtro del sistema de archivos heredados pueden evitar errores de programación comunes en las rutinas de envío.

Para obtener información sobre qué tipos de IRP se usan en la E/S de paginación, vea Dispatch Routine IRQL and Thread Context.

  • Las rutinas de envío en la ruta de acceso de E/S de paginación nunca deben llamar a IoCallDriver en cualquier IRQL mayor que APC_LEVEL. No se puede realizar la paginación de E/S (ni ninguna E/S) en DISPATCH_LEVEL porque el sistema usa LAS API para procesar la finalización de E/S, por lo que nunca vería completada la operación. Si una rutina de envío genera IRQL, debe reducirla antes de llamar a IoCallDriver.

  • No es necesariamente seguro que una rutina de envío llame a IoCallDriver en APC_LEVEL en todas las situaciones. Consulte IrQL de rutina de distribución y contexto de subprocesos para determinar si puede estar en APC_LEVEL o debe estar en PASSIVE_LEVEL.

  • Las rutinas de distribución en la ruta de acceso de E/S de paginación, como lectura y escritura, no pueden llamar de forma segura a ninguna rutina en modo kernel que requiera que los autores de llamadas se ejecuten en IRQL PASSIVE_LEVEL.

  • Las rutinas de envío que se encuentran en la ruta de acceso de E/S del archivo de paginación no pueden llamar de forma segura a ninguna rutina de modo kernel que requiera que un llamador se ejecute en IRQL < DISPATCH_LEVEL.

  • Las rutinas de envío que no están en la ruta de acceso de E/S de paginación nunca deben llamar a IoCallDriver en cualquier IRQL mayor que PASSIVE_LEVEL. Si una rutina de envío genera IRQL, debe reducirla antes de llamar a IoCallDriver.

Restricciones en los IRP de procesamiento

  • Si los parámetros IRP incluyen direcciones de espacio de usuario, estas direcciones se deben validar antes de que se usen. Para obtener más información, vea Errores en E/S almacenadas en búfer.

  • Además, si el IRP contiene un búfer IOCTL o FSCTL enviado desde una plataforma de 32 bits a una plataforma de 64 bits, es posible que el contenido del búfer tenga que ser matizado. Para obtener más información, consulte Compatibilidad con E/S de 32 bits en el controlador de 64 bits.

  • A diferencia de los sistemas de archivos, los controladores de filtro del sistema de archivos nunca deben llamar a FsRtlEnterFileSystem o FsRtlExitFileSystem , excepto antes de llamar a ExAcquireFastMutexUnsafe o ExAcquireResourceExclusiveLite. FsRtlEnterFileSystem y FsRtlExitFileSystem deshabilitan las API de kernel normales, que son necesarias para la mayoría de los sistemas de archivos.

  • No se pueden emitir otros IRP desde una ruta de acceso de E/S de paginación. Puede poner en cola un subproceso de trabajo que emite E/S, pero no debe esperar sincrónicamente para que se complete ese subproceso de trabajo porque la espera provoca interbloqueos.

Restricciones en la finalización de IRP

  • Los controladores de filtro del sistema de archivos solo deben usar los valores de estado correcto y de error al completar los IRP.

  • Aunque STATUS_PENDING es un valor NTSTATUS correcto, se trata de un error de programación para completar un IRP con STATUS_PENDING.

  • Después de que una rutina de distribución llame a IoCompleteRequest, el puntero IRP ya no es válido y no se puede desreferenciar de forma segura.

Restricciones al establecer una rutina de finalización

Para obtener información sobre cómo establecer rutinas de finalización, vea Usar rutinas de finalización.

  • Cuando una rutina de distribución llama a IoSetCompletionRoutine, puede pasar opcionalmente un puntero de contexto a una estructura para que la rutina de finalización la use al procesar el IRP especificado. Esta estructura debe asignarse desde un grupo no paginado, ya que la rutina de finalización se puede llamar IRQL DISPATCH_LEVEL.

  • Si una rutina de envío establece una rutina de finalización que puede devolver STATUS_MORE_PROCESSING_REQUIRED, debe realizar una de las siguientes acciones para evitar que el Administrador de E/S complete el IRP prematuramente:

Restricciones al pasar IRP hacia abajo

  • Después de que una rutina de envío llama a IoCallDriver, el puntero IRP ya no es válido y no se puede desreferenciar de forma segura, a menos que la rutina de envío espere a que se llame a la rutina de finalización.

  • Se trata de un error de programación para llamar a PoCallDriver desde un controlador de filtro del sistema de archivos. (PoCallDriver se usa para pasar solicitudes de IRP_MJ_POWER a controladores de nivel inferior. Los controladores de filtro del sistema de archivos nunca reciben IRP_MJ_POWER solicitudes).

Restricciones al devolver el estado

  • Excepto cuando se completa un IRP, una rutina de envío que no establece una rutina de finalización siempre debe devolver el valor NTSTATUS devuelto por IoCallDriver. A menos que este valor sea STATUS_PENDING, debe coincidir con el valor de Irp-IoStatus.Status> establecido por el controlador que completó el IRP.

  • Cuando IoCallDriver devuelve STATUS_PENDING, la rutina de envío también debe devolver STATUS_PENDING, a menos que espere a que la rutina de finalización indique un evento.

  • Cuando la rutina de envío envía el IRP a una cola de trabajo para su procesamiento posterior, debe marcar el IRP pendiente y devolver STATUS_PENDING.

  • Cuando la rutina de envío establece una rutina de finalización que podría publicar el IRP en una cola de trabajo para su procesamiento posterior, debe marcar el IRP pendiente y devolver STATUS_PENDING.

  • Una rutina de envío que marca un IRP pendiente debe devolver STATUS_PENDING.

  • Las operaciones de interbloqueo no se pueden bloquear (publicadas en una cola de trabajo) y las rutinas de envío no pueden devolver STATUS_PENDING para ellas.

Restricciones en la publicación de IRP en una cola de trabajo

  • Si una rutina de envío envía IRP a una cola de trabajo, debe llamar a IoMarkIrpPending antes de publicar cada IRP en la cola de trabajo. De lo contrario, el IRP podría quitarse de la cola, completarse con otra rutina de controlador y liberarse por el sistema antes de que se produzca la llamada a IoMarkIrpPending , lo que provoca un bloqueo.