Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En esta sección se describen las directrices para implementar una rutina Cancelar y gestionar IRPs cancelables. Para obtener más información sobre el control de IRPs cancelables, consulte el flujo de control para las colas de IRP Cancel-Safe.
Directrices generales para todas las rutinas de cancelación
El administrador de E/S mantiene el bloqueo de cancelación tipo spin lock cada vez que llama a la rutina Cancelar de un controlador de dispositivos. Por lo tanto, todas las rutinas Cancelar deben:
Llame a IoReleaseCancelSpinLock antes de devolver el control.
No llame a IoAcquireCancelSpinLock a menos que llame primero a IoReleaseCancelSpinLock .
Realice una llamada recíproca a IoReleaseCancelSpinLock para cada llamada que realiza a IoAcquireCancelSpinLock.
Cada vez que la rutina Cancelar llama a IoReleaseCancelSpinLock, debe pasar el IRQL devuelto por la llamada más reciente a IoAcquireCancelSpinLock. Al liberar el bloqueo de giro adquirido por el administrador de E/S (que se mantiene cuando se llamó a la rutina Cancel), la rutina Cancel debe pasar Irp->CancelIrql.
Un controlador no debe llamar a rutinas externas (como IoCompleteRequest) mientras mantiene un spinlock porque puede producirse un interbloqueo.
Uso de la cola definida por el Administrador de E/S
A menos que un controlador administre sus propias colas internas de IRP, se llama a su rutina Cancel con un IRP entrante que podría ser cualquiera de los siguientes:
CurrentIrp en el objeto de dispositivo de destino de entrada
Entrada en la cola de dispositivos asociada al objeto de dispositivo de destino
A menos que un controlador administre sus propias colas internas de IRP, su rutina Cancel debe llamar a KeRemoveEntryDeviceQueue con el IRP de entrada para probar si es una entrada en la cola de dispositivos asociada al objeto de dispositivo de destino. La rutina Cancel del controlador no puede llamar a KeRemoveDeviceQueue o KeRemoveByKeyDeviceQueue porque no puede suponer que el IRP dado está en cualquier posición determinada de la cola del dispositivo.
Estado actual del IRP de entrada
Si se llama a una rutina Cancel con un IRP para el que el controlador ya ha iniciado el procesamiento de E/S y la solicitud se completará pronto, la rutina Cancel debe liberar el spinlock de cancelación del sistema y devolver el control.
Si el estado actual del IRP de entrada es Pendiente, una rutina Cancelar debe hacer lo siguiente:
Establezca que el bloque de estado de E/S del IRP de entrada deberá tener STATUS_CANCELLED para Estado y cero para Información.
Suelte los bloqueos de giro que está sujetando, incluido el bloqueo de cancelación de giro del sistema.
Llame a IoCompleteRequest con el IRP especificado.
Retención de IRPs en estado cancelable
Cualquier rutina de controlador que contenga un IRP en un estado cancelable debe llamar a IoMarkIrpPending y debe llamar a IoSetCancelRoutine para establecer su punto de entrada para la rutina Cancel en IRP. Solo entonces puede esa rutina de controlador llamar a rutinas de soporte adicionales, como IoStartPacket, IoAllocateController o una rutina ExInterlockedInsert..List.
Cualquier rutina de controlador que posteriormente procese IRPs cancelables debe comprobar si un IRP ya ha sido cancelado antes de que comiencen las operaciones para satisfacer la solicitud. La rutina debe llamar a IoSetCancelRoutine para restablecer su punto de entrada para la rutina Cancelar a NULL en el IRP. Solo entonces puede esa rutina comenzar su procesamiento de E/S para el IRP de entrada.
Es posible que una rutina tenga que restablecer el punto de entrada de una rutina Cancel en un IRP si también pasa IRP para su posterior procesamiento por otras rutinas de controlador y esos IRP se pueden mantener en un estado cancelable.
Cualquier controlador de nivel superior que contenga un IRP en un estado cancelable debe restablecer su punto de entrada Cancelar a NULL antes de pasar el IRP al controlador siguiente inferior con IoCallDriver.
Cancelación de un IRP
Cualquier controlador de nivel superior puede llamar a IoCancelIrp con un IRP que ha asignado y pasado para que lo procesen controladores de nivel inferior. Sin embargo, este controlador no puede suponer que el IRP especificado se completará con STATUS_CANCELLED por controladores inferiores.
Sincronización
Un controlador puede (o debe, dependiendo de su diseño) mantener información de estado adicional en su extensión de dispositivo para realizar un seguimiento del estado de cancelación de los IRP. Si las rutinas de controlador que se ejecutan en IRQL <= DISPATCH_LEVEL comparten este estado, los datos compartidos deben protegerse con un bloqueo de giro asignado e inicializado por el controlador.
El controlador debe administrar cuidadosamente sus adquisiciones y liberaciones del bloqueo de giro de cancelación del sistema y sus propios bloqueos de giro. Debe mantener el bloqueo de giro de cancelación del sistema durante los intervalos más cortos posibles. Antes de acceder a un IRP cancelable, este controlador siempre debe comprobar el valor devuelto de IoSetCancelRoutine para determinar si la rutina Cancelar ya se está ejecutando (o está a punto de ejecutarse); si es así, debe dejar que la rutina Cancelar complete el IRP.
Si un controlador de dispositivo mantiene información de estado sobre IRP cancelables que varias rutinas del controlador comparten con su ISR, estas otras rutinas deben sincronizar el acceso al estado compartido con el ISR. Solo una rutina synchCritSection proporcionada por el controlador puede acceder a la información de estado que se comparte con el ISR de forma segura para varios procesadores.
Para obtener más información, consulte Técnicas de sincronización.