INFORMACIÓN: Sugerencias para Windows NT Driver Developers--cosas para evitar

Seleccione idioma Seleccione idioma
Id. de artículo: 186775 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

Resumen

Siguiente encontrará algunas sugerencias para crear controladores de dispositivo de Windows NT. Las sugerencias presentadas se aplican a todas las tecnologías. También puede utilizar esto como una lista de comprobación para solucionar problemas de controlador.

Debe tener un conocimiento básico de arquitectura de Windows NT y algunas desarrollo del controlador de dispositivo experimentar para utilizar la información presentan debajo de forma eficaz. Para obtener más información sobre desarrollo de controlador de dispositivo, consulte el kit de controlador de dispositivo de Windows (DDK), que está disponible mediante suscripción de MSDN Professional.

Más información

Siguiente es una lista de cosas que los desarrolladores deben evitar cuando se trabaja con controladores de dispositivo de Windows NT:

  1. STATUS_PENDING nunca devuelto desde una rutina de envío sin marcar el paquete de solicitud de E/s (IRP) pendiente (IoMarkIrpPending).
  2. Nunca llame a KeSynchronizeExecution desde una rutina de servicio de interrupción (ISR). Interbloquearán su sistema.
  3. Nunca establezca DeviceObject-> Flags en DO_BUFFERED_IO y DO_DIRECT_IO. Puede confundir el sistema y finalmente producir error grave. Además, nunca establezca METHOD_BUFFERED, METHOD_NEITHER, METHOD_IN_DIRECT o METHOD_OUT_DIRECT en DeviceObject-> marcas, debido a que estos valores sólo se utilizan en la definición IOCTL.
  4. No asignar nunca distribuidor objetos desde un bloque paginado. Si lo hace, provocará bugchecks ocasional del sistema.
  5. Nunca asignar memoria del bloque paginado o acceso a memoria de bloque paginado, mientras se ejecuta en una IRQL > = DISPATCH_LEVEL. Es un error grave.
  6. Nunca espere en un objeto de núcleo distribuidor un intervalo distinto de cero en una IRQL > = DISPATCH_LEVEL. Es un error grave.
  7. Nunca llamada cualquier función que provoca la llamada del subproceso espere directamente o indirectamente mientras se ejecuta en una IRQL > = DISPATCH_LEVEL. Es un error grave.
  8. Nunca disminuir el nivel de solicitud de interrupción (IRQL) debajo del nivel en el que se ha invocado la rutina de nivel superior.
  9. Llamar nunca a KeLowerIrql() si no ha llamado a KeRaiseIrql().
  10. Plaza nunca un procesador (KeStallExecutionProcessor) más de 50 microsegundos.
  11. Nunca bloqueos cualquier número mayor que sea necesario. Para mejor rendimiento general de sistema, no mantenga los bloqueos de giro de todo el sistema más de 25 microsegundos.
  12. Nunca llame a KeAcquireSpinLock y KeReleaseSpinLock, o KeAcquireSpinLockAtDpcLevel y KeReleaseSpinLockFromDpcLevel, mientras se ejecuta en una IRQL mayor DISPATCH_LEVEL.
  13. Nunca debe liberar un bloqueo de bucle que adquirió con KeAcquireSpinLock KeReleaseSpinLockFromDpcLevel llamada, porque no se restaurará la IRQL original.
  14. Nunca llame a KeAcquireSpinLock y KeReleaseSpinLock o cualquier otra rutina que utiliza un bloqueo de bucle ejecutivo desde un routine(s) ISR o SynchCritSection.
  15. Nunca se olvide de Borrar marca DO_DEVICE_INITIALIZING cuando se crea un objeto de dispositivo en una rutina distinto DriverEntry.
  16. Nunca cola un objeto de llamada (DPC) de procedimiento diferido (utilizando KeInsertQueueDpc) con varios subprocesos en procesadores diferentes simultáneamente. Puede conducir a error grave.
  17. No desasignar nunca un temporizador periódico de una rutina CutomerTimerDPC. Puede desasignar los temporizadores no periódicas desde una rutina DPC.
  18. Nunca pasar el mismo puntero DPC a KeSetTimer o KeSetTimerEx (CustomTimerDpc) y KeInsertQueueDpc (CustomDpc), porque hace que las condiciones de anticipación.
  19. Nunca llame a IoStartNextPacket mientras mantiene un bloqueo de bucle. Puede interbloqueo del sistema.
  20. Nunca llame a IoCompleteRequest mientras mantiene un bloqueo de bucle. Puede interbloqueo del sistema.
  21. Nunca llame a IoCompleteRequest sin establecer la rutina de finalización en NULL si el controlador establece la rutina de finalización.
  22. Nunca se olvide de establecer el bloque de estado de E/s en el IRP antes de llamar a IoCompleteRequest.
  23. Nunca llame a IoMarkPending después de la cola un IRP o enviar a otro controlador (IoCallDriver). El IRP puede completarse antes de que el controlador llama a IoMarkPending y podría producirse una comprobación de errores. Para los controladores con rutinas de finalización, las rutinas de finalización deben llamar a IoMarkPending si se establece IRP-> PendingReturned.
  24. No tocar un IRP nunca después de llamar a IoCompleteRequest en él.
  25. Nunca llame a IoCancelIrp en un IRP que no pertenece a su controlador a menos que sepa que el IRP no se ha completado todavía.
  26. Nunca llame a IoCancelIrp para el IRP su rutina de envío está trabajando hasta que la rutina de envío se devuelve al llamador.
  27. Nunca llame a IoMakeAssociatedIrp crear IRP para controladores inferiores de un controlador intermedio. El IRP obtendrá en su controlador intermedio puede ser un IRP asociado y no se puede asociar otro IRP a una IRP ya asociado.
  28. Nunca IoMakeAssociatedIrp en un IRP que se ha configurado para realizar llamada búfer de E/s.
  29. Nunca simplemente eliminar virtuales punteros a registros de E/s de dispositivo y obtener acceso a ellos. Utilice siempre las funciones de capa (HAL) de abstracción de hardware adecuado para acceso a un dispositivo.
  30. Nunca tener acceso a campos de objeto IRP o dispositivo desde una ISR que se puede modificar desde DISPATCH_LEVEL. En un sistema multiprocesador simétrico Esto puede provocar daños en los datos.
  31. Nunca modificar datos mientras se ejecuta en una IRQL alto si los datos pueden escribirse por código de IRQL de baja. Utilizar la rutina KeSynchronizeExecution.
  32. Nunca adquirir uno de los bloqueos de giro del controlador (si tiene alguna) en la rutina DispatchCleanup, antes de adquirir el bloqueo de bucle Cancelar todo el sistema (IoAcquireCancelSpinLock). Después de una jerarquía de adquisición de bloqueo coherente en todo el controlador son esencial para evitar posibles interbloqueos.
  33. Nunca llamada IoAcquireCancelSpinLock en la rutina cancelar porque siempre se llama con el sistema Cancelar número bloqueo se mantiene en su nombre.
  34. Nunca se olvide de llamar al IoReleaseCancelSpinLock antes de devolver desde una rutina de cancelación.
  35. Nunca utilice sincronización basada en IRQL porque esto sólo funciona en sistemas de procesador único. Provocar IRQL en un procesador no máscara interrupciones en otros procesadores.
  36. Nunca utilice RtlCopyMemory para intervalos de direcciones de memoria superpuesta. Utilice RtlMoveMemory.
  37. No suponga nunca tamaños de página están constantes, incluso para una determinada CPU. Utilice PAGE_SIZE y otros relacionados con las constantes definidas en archivos de encabezado para mantener la portabilidad de página.
  38. Nunca tener acceso a las claves del registro distinto Registry\Machine\Hardware y Registry\Machine\System desde la rutina de DriverEntry de un controlador cargado en la fase de inicialización de Boot\System.
  39. No crear nunca una clave de enumeración para cargar un controlador de clave de registro del controlador (Registry\Machine\System\CurrentControlSet\Services). El sistema crea esta clave dinámicamente.
  40. Nunca se intenta inicializar un dispositivo físico sin que los puertos de E/s bus relativa necesarios, intervalos de memoria, interrupción o acceso directo a memoria (DMA) canal y puerto recursos de hardware en el registro por primera vez.
  41. Nunca llame a IoRegisterDriverReinitialization desde su DriverEntry rutinarias a menos que devuelve STATUS_SUCCESS.
  42. Llamar nunca a KeSetEvent con el parámetro espera establecido en TRUE desde un subproceso paginable o rutina de controlador paginable que se ejecuta en IRQL PASSIVE_LEVEL. Este tipo de llamada hace que un error de página grave si la rutina se paginan entre las llamadas a KeSetEvent KeWaitObjeto (s).
  43. Llamar nunca a KeReleaseSemaphore con el parámetro espera establecido en TRUE desde un subproceso paginable o rutina de controlador paginable que se ejecuta en IRQL PASSIVE_LEVEL. Si la rutina se paginan entre las llamadas a KeReleaseSemaphore KeWaitObjetos, este tipo de una llamada hace que un error de página grave.
  44. Llamar nunca a KeReleaseMutex con el parámetro espera establecido en TRUE desde un subproceso paginable o rutina de controlador paginable que se ejecuta en IRQL PASSIVE_LEVEL. Si la rutina se paginan entre las llamadas a KeReleaseMutex KeWaitObjetos, este tipo de una llamada hace que un error de página grave.
  45. Nunca llame a KeBugCheckEx+0x19 o KeBugCheck desde un controlador de Windows comercial para reducir el sistema, a menos que el error es un error crítico que podría dañar la memoria del sistema o provocar finalmente que el sistema comprobación de errores. Siempre intentará controlar las condiciones de error correctamente.
  46. Nunca dé por supuesto que una rutina IoTimer se llamará con precisión en un límite de un segundo porque los intervalos en que cualquier IoTimer determinado se llama rutina depende en última instancia resolución del reloj del sistema.
  47. Nunca llame a interfaces de programación de aplicaciones (API) de Win32s desde un controlador de dispositivo de modo de núcleo.
  48. Nunca utilice recursiva funciones que pueden provocar la pila de desbordamiento porque la llamada pila del subproceso de modo núcleo no aumenta dinámicamente mientras se está ejecutando en modo de núcleo.
  49. Nunca utilice punteros de objeto de interrupción (PKINTERRUPT) que controla más de una interrupción, para identificar las interrupciones de una ISR, ya que la dirección del objeto interrupción que obtendrá en el ISR no siempre será el mismo que obtuvo de IoConnectInterrupt. Sólo debe utilizar el valor de ServiceContext que especifique en IoConnectInterrupt para identificar el dispositivo de interrupción actual.
  50. No descargar nunca un controlador sin borrar CustomTimerDpc (KeCancelTimer). Si el DPC se desencadena después de descargar el controlador, podría visitas sin código existente y provocar que el sistema comprobación de errores.
  51. Nunca descargar un controlador hasta que todas los IRP de tiene el CompletionRoutine de E/s del controlador establecido en el se completan. Si el IRP obtiene completado por el controlador inferior después de descargar el controlador, el sistema podría intentar ejecutar el código inexistente y provocar que el sistema se bloquee.
  52. Nunca habilita interrupción del dispositivo hasta que el controlador está preparado para controlarla. Debe habilitar sólo después de su controlador está totalmente inicializado y es seguro para el sistema que tocar las estructuras internas del controlador de ISR y de DPC.
  53. Nunca llamada fuera de su controlador manteniendo un spinlock ya que puede provocar interbloqueos.
  54. Nunca devuelto cualquier estado distinto STATUS_MORE_PROCESSING_REQUIRED desde su CompletionRoutine de E/s para un IRP creado por el controlador con IoBuildAsynchronousFsdRequest/IoAllocateIrp porque el IRP no está preparado para la finalización relacionada con procesamiento posterior por el Administrador de E/s. Un IRP de tal debe liberarse explícitamente (IoFreeIrp) por el controlador. Si el IRP no está destinado a reutilizar, puede liberarse en el CompletionRoutine antes de devolver el estado STATUS_MORE_PROCESSING_REQUIRED.
  55. No asignar nunca un IRP con IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest en un contexto de subproceso arbitrario porque el IRP permanece asociado con el subproceso (IRP-> ThreadListEntry) hasta que se libera.
  56. Nunca llame a IoInitializeIrp en un IRP que se ha asignado con IoAllocateIrp con ChargeQuota parámetro establecido en TRUE. Al asignar un IRP con ChargeQuota establecido en TRUE, el Administrador de E/s mantiene la información sobre el grupo desde el cual que asignar la memoria para el IRP de indicador interno del IRP.

    Cuando se llama a IoInitializeIrp tal un IRP, la información de grupo de asignación se pierde como esta función ciegamente ceros IRP de todo. Esto provoca daños en la memoria al liberar el IRP. Además, nunca reutilizar un IRP a la que procede el Administrador de E/S. Si desea reutilizar un IRP, debe asignar su propio utilizando IoAllocateIrp.
  57. Nunca especifique WaitMode como UserMode en KeWaitForSingleObject/KeWaitForMultipleObjects si se asigna el objeto en la pila del subproceso de llamada. La consecuencia de esto es que, si el objeto se ha atendido se crea en la pila de función, debe especificar KernelMode como el WaitMode para impedir que la pila de subprocesos que se va a paginar.
  58. Nunca adquirir recursos como ERESOURCES FastMutex(Unsafe) en el contexto de un subproceso de modo de usuario sin proteger el código de una sección crítica.

    Puesto que la adquisición de estos recursos no provoca la IRQL a APC_LEVEL, si el subproceso es suspendido (hecho en cola una APC) después de ha adquirido el recurso, se podría producir interbloqueo y poner en peligro la seguridad de sistema. Por lo tanto, debe adquirir estos recursos, ya sea levantando explícitamente la IRQL APC_LEVEL o en una sección crítica llamando KeEnterCriticalRegion.

Referencias

Guía de diseño de controlador de dispositivo de MSDN para Windows NT

Propiedades

Id. de artículo: 186775 - Última revisión: martes, 27 de julio de 2004 - Versión: 2.1
La información de este artículo se refiere a:
  • Microsoft Win32 Device Driver Kit for Windows NT 3.51
  • Microsoft Win32 Device Driver Kit for Windows NT 4.0
Palabras clave: 
kbmt kbinfo KB186775 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 186775
Renuncia a responsabilidad de los contenidos de la KB sobre productos a los que ya no se ofrece asistencia alguna
El presente artículo se escribió para productos para los que Microsoft ya no ofrece soporte técnico. Por tanto, el presente artículo se ofrece "tal cual" y no será actualizado.

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com