Compartir vía


Extensiones de dispositivo

Para la mayoría de los controladores intermedios y de nivel más bajo, la extensión del dispositivo es la estructura de datos más importante asociada a un objeto de dispositivo. Su estructura interna está definida por el controlador y se usa normalmente para:

  • Mantenga la información de estado del dispositivo.

  • Proporcione almacenamiento para cualquier objeto definido por kernel u otros recursos del sistema, como bloqueos de número, que usa el controlador.

  • Mantenga los datos que el controlador deba tener residentes y en el espacio del sistema para llevar a cabo sus operaciones de E/S.

Dado que la mayoría de los controladores de bus, función y filtro (controladores de nivel más bajo e intermedios) se ejecutan en un contexto de subproceso arbitrario (el de cualquier subproceso que sucede para estar actual), una extensión de dispositivo es el lugar principal de cada controlador para mantener el estado del dispositivo y todos los demás datos específicos del dispositivo que necesita el controlador. Por ejemplo, cualquier controlador que implemente una rutina CustomTimerDpc o CustomDpc normalmente proporciona almacenamiento para el temporizador definido por el kernel y/o los objetos DPC necesarios en una extensión de dispositivo.

Cada controlador que tenga un ISR debe proporcionar almacenamiento para un puntero a un conjunto de objetos de interrupción definidos por el kernel, y la mayoría de los controladores de dispositivo almacenan este puntero en una extensión de dispositivo. Cada controlador determina el tamaño de la extensión de dispositivo cuando crea un objeto de dispositivo y cada controlador define el contenido y la estructura de sus propias extensiones de dispositivo.

Las rutinas IoCreateDevice e IoCreateDeviceSecure del administrador de E/S asignan memoria para el objeto de dispositivo y la extensión del grupo de memoria no paginado.

Cada rutina de controlador estándar que recibe un IRP también recibe un puntero a un objeto de dispositivo que representa el dispositivo de destino para la operación de E/S solicitada. Estas rutinas de controlador pueden acceder a la extensión de dispositivo correspondiente a través de este puntero. Normalmente, un puntero DeviceObject también es un parámetro de entrada para un ISR del controlador de nivel más bajo.

En la ilustración siguiente se muestra un conjunto representativo de datos definidos por el controlador para la extensión del dispositivo de un objeto de dispositivo de nivel inferior. Un controlador de nivel superior no proporcionaría almacenamiento para un puntero de objeto de interrupción devuelto por IoConnectInterrupt y pasado a KeSynchronizeExecution e IoDisconnectInterrupt. Sin embargo, un controlador de nivel superior proporcionaría almacenamiento para el temporizador y los objetos DPC que se muestran en la ilustración siguiente si el controlador tiene una rutina CustomTimerDpc . Un controlador de nivel superior también puede proporcionar almacenamiento para un bloqueo de número ejecutivo y una cola de trabajo interbloqueada.

diagrama que ilustra una extensión de dispositivo de ejemplo para un controlador de nivel inferior.

Además de proporcionar almacenamiento para un puntero de objeto de interrupción, un controlador de dispositivo de nivel más bajo debe proporcionar almacenamiento para un bloqueo de número de interrupción si su ISR controla las interrupciones de dos o más dispositivos en vectores diferentes o si tiene más de un ISR. Para obtener más información sobre cómo registrar un ISR, consulte Registro de un ISR.

Normalmente, los controladores almacenan punteros a sus objetos de dispositivo en sus extensiones de dispositivo, como se muestra en la ilustración. Un controlador también puede conservar una copia de la lista de recursos del dispositivo en la extensión.

Normalmente, un controlador de nivel superior almacena un puntero al objeto de dispositivo del controlador inferior siguiente en su extensión de dispositivo. Un controlador de nivel superior debe pasar un puntero al objeto de dispositivo del controlador inferior siguiente a IoCallDriver, después de configurar la ubicación de pila de E/S del controlador siguiente inferior en un IRP, como se explica en Control de IRP.

Tenga en cuenta también que cualquier controlador de nivel superior que asigne IRP para controladores de nivel inferior debe especificar cuántas ubicaciones de pila deben tener las nuevas IRP. En concreto, si un controlador de nivel superior llama a IoMakeAssociatedIrp, IoAllocateIrp o IoInitializeIrp, debe tener acceso al objeto de dispositivo de destino del controlador de nivel inferior siguiente para leer su valor stackSize , con el fin de proporcionar el stackSize correcto como argumento para estas rutinas de soporte técnico.

Aunque un controlador de nivel superior puede leer datos del objeto de dispositivo del controlador de nivel inferior siguiente a través del puntero devuelto por IoAttachDeviceToDeviceStack, este controlador debe seguir estas directrices de implementación:

  • Nunca intente escribir datos en el objeto de dispositivo del controlador inferior.

    Las únicas excepciones a esta guía son los sistemas de archivos, que establecen y borran DO_VERIFY_VOLUME en las marcas de los objetos de dispositivo de los controladores de medios extraíbles de nivel inferior.

  • Nunca intente acceder a la extensión del dispositivo del controlador inferior por los siguientes motivos:

    • No hay ninguna manera segura de sincronizar el acceso a una sola extensión de dispositivo entre dos controladores.

    • Un par de controladores que implementan este esquema de comunicación de backdoor no se puede actualizar individualmente, no puede tener un controlador intermedio insertado entre ellos sin cambiar el origen del controlador existente y no se puede volver a compilar y mover fácilmente de una plataforma Windows a la siguiente.

Para conservar su interoperabilidad con controladores de nivel inferior de una plataforma o versión de Windows a la siguiente, los controladores de nivel superior deben reutilizar los IRP dados o deben crear nuevos IRP y deben usar IoCallDriver para comunicar las solicitudes a los controladores de nivel inferior.