Introducción a los objetos de distribuidor de kernel

El kernel define un conjunto de tipos de objetos denominados objetos de distribuidor de kernel o simplemente objetos de distribuidor. Los objetos Dispatcher incluyen objetos de temporizador, objetos de evento, objetos de semáforo, objetos de exclusión mutua y objetos de subproceso.

Los controladores pueden usar objetos de distribuidor como mecanismos de sincronización dentro de un contexto de subproceso nobitrario mientras se ejecuta en IRQL igual a PASSIVE_LEVEL.

Estados del objeto Dispatcher

Cada tipo de objeto de distribuidor definido por kernel tiene un estado establecido en Signaled o establecido en Not-Signaled.

Un grupo de subprocesos puede sincronizar sus operaciones si uno o varios subprocesos llaman a KeWaitForSingleObject, KeWaitForMutexObject o KeWaitForMultipleObjects. Estas funciones toman punteros de objeto de distribuidor como entrada y esperan hasta que otra rutina o subproceso establece uno o varios objetos de distribuidor en el estado Signaled.

Cuando un subproceso llama a KeWaitForSingleObject para esperar un objeto distribuidor (o KeWaitForMutexObject para una exclusión mutua), el subproceso se coloca en un estado de espera hasta que el objeto distribuidor se establece en el estado Signaled. Un subproceso puede llamar a KeWaitForMultipleObjects para esperar a que se establezca en Signaled un conjunto de objetos de distribuidor o para todos.

Cada vez que un objeto distribuidor se establece en el estado Signaled, el kernel cambia el estado de cualquier subproceso que espera a que ese objeto esté listo. (Los temporizadores de sincronización y los eventos de sincronización son excepciones a esta regla; cuando se señala un evento de sincronización o temporizador, solo se establece un subproceso en espera en el estado listo. Para obtener más información, vea Objetos de temporizador y DDC yObjetos de evento). Un subproceso en estado listo se programará para ejecutarse según su prioridad de subproceso en tiempo de ejecución actual y la disponibilidad actual de los procesadores para cualquier subproceso con esa prioridad.

¿Cuándo pueden los controladores esperar objetos dispatcher?

En general, los controladores pueden esperar a que se establezcan objetos de distribuidor solo si se cumple al menos una de las siguientes circunstancias:

  • El controlador se está ejecutando en un contexto de subproceso nobitrario.

    Es decir, puede identificar el subproceso que entrará en un estado de espera. En la práctica, las únicas rutinas de controlador que se ejecutan en un contexto de subproceso nobitrario son driverEntry, AddDevice, Reinitialize y Unload rutinas de cualquier controlador, además de las rutinas de distribución de los controladores de nivel superior. El sistema llama directamente a todas estas rutinas.

  • El controlador está realizando una solicitud de E/S completamente sincrónica.

    Es decir, ningún controlador pone en cola ninguna operación mientras controla la solicitud de E/S y ningún controlador vuelve hasta que el controlador debajo ha terminado de controlar la solicitud.

Además, un controlador no puede especificar un estado de espera si se ejecuta en irQL o superior igual a DISPATCH_LEVEL.

En función de estas limitaciones, debe usar las reglas siguientes:

  • Las rutinas DriverEntry, AddDevice, Reinitialize y Unload de cualquier controlador pueden esperar objetos de distribuidor.

  • Las rutinas de envío de un controlador de nivel superior pueden esperar objetos de distribuidor.

  • Las rutinas de distribución de los controladores de nivel inferior pueden esperar objetos de envío, si la operación de E/S es sincrónica, como crear, vaciar, apagar y cerrar operaciones, algunas operaciones de control de E/S de dispositivo y algunas operaciones de alimentación y PnP.

  • Las rutinas de distribución de los controladores de nivel inferior no pueden esperar a que un objeto distribuidor finalice las operaciones de E/S asincrónicas.

  • Una rutina de controlador que se ejecuta en irQL o superior DISPATCH_LEVEL no debe esperar a que un objeto distribuidor se establezca en el estado Signaled.

  • Un controlador no debe intentar esperar a que un objeto distribuidor se establezca en el estado Signaled para la finalización de una operación de transferencia hacia o desde un dispositivo de paginación.

  • Por lo general, las rutinas de envío de controladores que atienden las solicitudes de lectura y escritura no pueden esperar a que un objeto distribuidor se establezca en el estado Signaled.

  • Una rutina de distribución para una solicitud de control de E/S de dispositivo puede esperar a que un objeto distribuidor se establezca en el estado Signaled solo si el tipo de transferencia para el código de control de E/S es METHOD_BUFFERED.

  • Los controladores de minipuerto SCSI no deben usar objetos de distribuidor del kernel. Los controladores de minipuerto SCSI solo deben llamar a rutinas de biblioteca de puertos SCSI.

Todas las demás rutinas de controlador estándar se ejecutan en un contexto de subproceso arbitrario: el de cualquier subproceso que ocurra como actual cuando se llama a la rutina del controlador para procesar una operación en cola o para controlar una interrupción del dispositivo. Además, la mayoría de las rutinas de controlador estándar se ejecutan en un IRQL elevado, ya sea en DISPATCH_LEVEL o en controladores de dispositivos, en DIRQL.

Si es necesario, un controlador puede crear un subproceso dedicado al dispositivo, que puede esperar a que las demás rutinas del controlador (excepto una rutina ISR o SynchCritSection ) establezcan un objeto de distribuidor en el estado Signaled y se restablezcan al estado de Not-Signaled.

Como guía general, si espera que el nuevo controlador de dispositivo a menudo tenga que detenerse durante más de 50 microsegundos mientras espera cambios en el estado del dispositivo durante las operaciones de E/S, considere la posibilidad de implementar un controlador con un subproceso dedicado al dispositivo. Si el controlador de dispositivo también es un controlador de nivel superior, considere la posibilidad de usar subprocesos de trabajo del sistema e implementar una o varias rutinas de devolución de llamada de subprocesos de trabajo. Consulte PsCreateSystemThread and Managing Interlocked Queues with a Driver-Created Thread (PsCreateSystemThread and Managing Interlocked Queues with a Driver-Created Thread).