Information : Conseils pour Windows NT Driver Developers--choses à éviter

Traductions disponibles Traductions disponibles
Numéro d'article: 186775 - Voir les produits auxquels s'applique cet article
Agrandir tout | Réduire tout

Résumé

Voici quelques conseils pour la création de pilotes de périphériques de Windows NT. Les conseils présentés s'appliquent à toutes les technologies. Vous pouvez également utiliser ceci comme une liste de contrôle pour la résolution des problèmes de pilote.

Vous devez avoir une connaissance de base de l'architecture de Windows NT et certains développement de pilotes de périphérique rencontrer pour utiliser les informations présentées ci-dessous efficacement. Pour plus d'informations sur le développement de pilote de périphérique, veuillez consulter le kit de pilote de périphérique Windows NT (DDK), qui est disponible via l'appartenance MSDN Professional.

Plus d'informations

Voici une liste des choses que les développeurs doivent éviter lorsque vous travaillez avec des pilotes de périphériques de Windows NT :

  1. Ne jamais retour STATUS_PENDING à partir d'une routine de diffusion sans marquer le paquet de demande d'e/S (IRP) en attente (IoMarkIrpPending).
  2. Ne jamais appeler KeSynchronizeExecution à partir d'une routine du service d'interruption (ISR). Il va se bloquer votre système.
  3. Valeur jamais DeviceObject-> indicateurs DO_BUFFERED_IO et DO_DIRECT_IO. Il faut confondre le système et finalement conduire à erreur fatale. En outre, jamais définie METHOD_BUFFERED, METHOD_NEITHER, METHOD_IN_DIRECT ou METHOD_OUT_DIRECT dans DeviceObject-> indicateurs, comme ces valeurs ne sont utilisés pour la définition d'IOCTL.
  4. Ne jamais allouer des objets de répartiteur à partir d'un pool paginé. Dans ce cas, il entraîne système occasionnels de bogues.
  5. Ne jamais allouer de mémoire à partir de pool paginé ou l'accès mémoire en pool paginé, lors de l'exécution à un niveau IRQL > = niveau DISPATCH_LEVEL. Il s'agit d'une erreur fatale.
  6. Ne jamais attendre sur un objet de répartiteur de noyau pour un intervalle différent de zéro à un niveau IRQL > = niveau DISPATCH_LEVEL. Il s'agit d'une erreur fatale.
  7. Jamais appel une fonction qui force le thread appelant à attendre directement ou indirectement lors de l'exécution à un niveau IRQL > = niveau DISPATCH_LEVEL. Il s'agit d'une erreur fatale.
  8. Jamais baisser le niveau de demande d'interruption (IRQL) sous le niveau auquel votre routine de niveau supérieur a été appelée.
  9. Ne jamais appeler KeLowerIrql() si vous n'avez pas appelé la méthode KeRaiseIrql().
  10. Place un processeur (KeStallExecutionProcessor) plu de 50 microsecondes de jamais.
  11. Jamais maintenir les verrous de rotation plus longtemps que nécessaire. Pour obtenir de meilleures performances système globales, ne contiennent pas de verrous de rotation à l'échelle du système plus de 25 microsecondes.
  12. Ne jamais appeler KeAcquireSpinLock et KeReleaseSpinLock, ou KeAcquireSpinLockAtDpcLevel et KeReleaseSpinLockFromDpcLevel, lors de l'exécution à un niveau IRQL supérieur au niveau DISPATCH_LEVEL.
  13. Jamais libérer un verrou de rotation a été acquis avec KeAcquireSpinLock en appelant KeReleaseSpinLockFromDpcLevel, car l'IRQL d'origine n'est pas restauré.
  14. Ne jamais appeler KeAcquireSpinLock et KeReleaseSpinLock ou toute autre routine qui utilise un verrou de rotation direction à partir d'un routine(s) ISR ou SynchCritSection.
  15. Jamais vous oubliez de désactiver indicateur DO_DEVICE_INITIALIZING lorsque vous créez un objet de périphérique dans une routine autres que DriverEntry.
  16. Mettre en file jamais d'attente un objet d'appel de procédures différés (à l'aide de KeInsertQueueDpc) avec plusieurs threads sur différents processeurs simultanément. Il peut entraîner l'erreur irrécupérable.
  17. Ne jamais libérer une minuterie périodique à partir d'une routine CutomerTimerDPC. Vous pouvez désallouer minuteries non périodiques à partir d'une routine DPC.
  18. Ne jamais passer le même pointeur DPC à KeSetTimer ou KeSetTimerEx (CustomTimerDpc) et KeInsertQueueDpc (CustomDpc), car il provoque conditions de concurrence critique.
  19. Ne jamais appeler IoStartNextPacket tout en maintenant un verrou de rotation. Il peut se bloquer votre système.
  20. Ne jamais appeler IoCompleteRequest tout en maintenant un verrou de rotation. Il peut se bloquer votre système.
  21. Ne jamais appeler IoCompleteRequest sans définir la routine d'achèvement avec la valeur NULL si votre pilote définit la routine d'achèvement.
  22. Ne jamais oublient de définir le bloc d'état e/S dans l'IRP avant d'appeler IoCompleteRequest.
  23. Ne jamais appeler IoMarkPending après mise en file d'attente un IRP ou l'envoi à un autre pilote (IoCallDriver). La Commission de contrôle internationale peut aboutir pour que le pilote appelle IoMarkPending et une vérification d'erreur peut se produire. Pour les pilotes avec les routines de fin, les routines de fin doivent appeler IoMarkPending si IRP-> PendingReturned est définie.
  24. Ne jamais toucher un IRP après avoir appelé IoCompleteRequest dessus.
  25. Ne jamais appeler IoCancelIrp sur un paquet IRP n'est pas détenu par votre pilote sauf si vous savez que l'IRP n'a pas encore été terminé.
  26. Ne jamais appeler IoCancelIrp pour le IRP votre routine de diffusion travaille sur jusqu'à ce que votre routine de diffusion renvoie à l'appelant.
  27. Ne jamais appeler IoMakeAssociatedIrp pour créer les paquets IRP pour pilotes inférieurs à partir d'un pilote intermédiaire. L'IRP vous recevez dans votre pilote intermédiaire peut être un IRP associé et vous ne pouvez pas associer d'autres IRP à un IRP déjà associé.
  28. Jamais appel IoMakeAssociatedIrp sur un IRP est configuré pour effectuer des mises en mémoire tampon d'e/S.
  29. Ne jamais simplement déréférencer virtuels des pointeurs vers des registres de périphérique d'e/S et y accéder. Toujours utiliser des fonctions de couche d'abstraction matérielle (HAL) d'abstraction de matériel approprié pour accéder à un périphérique.
  30. Ne jamais accès IRP ou périphérique objet champs à partir d'un ISR peuvent être modifiées à partir de niveau DISPATCH_LEVEL. Sur un système multiprocesseur symétrique, cela peut entraîner la corruption des données.
  31. Ne jamais modifier les données lors de l'exécution à un niveau IRQL élevé si ces données peuvent être écrit par le code de niveau IRQL faible. Utilisez la routine KeSynchronizeExecution.
  32. Jamais acquérir un des verrous de rotation du pilote (si vous avez une) dans votre routine DispatchCleanup, avant d'acquérir le verrou de rotation à l'échelle du système Annuler (IoAcquireCancelSpinLock). Suivant une hiérarchie d'acquisition de verrou cohérente tout au long de votre pilote est essentielle pour éviter les blocages potentiels.
  33. Ne jamais appel IoAcquireCancelSpinLock dans votre routine d'annulation, car elle est toujours appelée avec le système Annuler le verrou de rotation maintenu en son nom.
  34. Jamais vous oubliez d'appeler IoReleaseCancelSpinLock avant le renvoi d'une routine d'annulation.
  35. N'utilisez jamais synchronisation basée sur un niveau IRQL car cela fonctionne uniquement sur les systèmes à processeur unique. Déclenchement IRQL sur un seul processeur ne masque pas interruptions sur les autres processeurs.
  36. N'utilisez jamais RtlCopyMemory pour les plages d'adresses mémoire avec chevauchement. Utilisation RtlMoveMemory.
  37. Ne supposez jamais tailles de page sont constants, même pour une CPU donnée. Utilisation PAGE_SIZE et l'autre page connexes constantes définies dans les fichiers d'en-tête pour maintenir la portabilité.
  38. Ne jamais accéder à des clés de Registre autres que Registry\Machine\Hardware et Registry\Machine\System à partir de la routine DriverEntry d'un pilote chargé dans la phase d'initialisation Boot\System.
  39. Ne jamais créer une clé Enum pour charger un pilote sous la clé de Registre du pilote (Registry\Machine\System\CurrentControlSet\Services). Le système crée dynamiquement cette clé.
  40. Ne jamais tentative d'initialisation d'un périphérique physique sans prétendant nécessaires relatifs à un bus d'e/S ports, des plages de mémoire, des interruptions ou des accès direct à la mémoire (DMA) canal/port ressources matérielles dans le Registre tout d'abord.
  41. Ne jamais appeler IoRegisterDriverReinitialization à partir de votre DriverEntry routine, sauf si elle retourne STATUS_SUCCESS.
  42. Ne jamais appeler KeSetEvent avec le paramètre Wait défini avec la valeur TRUE à partir d'un thread paginable ou la routine de pilote paginables qui s'exécute au niveau IRQL PASSIVE_LEVEL. Ce type d'appel provoque une erreur irrécupérable page si votre routine paginées entre les appels à KeSetEvent et KeWaitObjet (s).
  43. Ne jamais appeler KeReleaseSemaphore avec le paramètre Wait défini avec la valeur TRUE à partir d'un thread paginable ou la routine de pilote paginables qui s'exécute au niveau IRQL PASSIVE_LEVEL. Si votre routine paginées entre les appels à KeReleaseSemaphore et KeWaitObjets, ce type d'un appel provoque une erreur irrécupérable de page.
  44. Ne jamais appeler KeReleaseMutex avec le paramètre Wait défini avec la valeur TRUE à partir d'un thread paginable ou la routine de pilote paginables qui s'exécute au niveau IRQL PASSIVE_LEVEL. Si votre routine paginées entre les appels à KeReleaseMutex et KeWaitObjets, ce type d'un appel provoque une erreur irrécupérable de page.
  45. Ne jamais appeler KeBugCheckEx ou KeBugCheck à partir d'un pilote de Windows NT de vente au détail pour mettre le système hors, sauf si l'erreur rencontrée est une erreur critique qui pourrait corrompre la mémoire système ou finalement pousser le système à la vérification d'erreur. Essayez toujours de gérer correctement les conditions d'erreur.
  46. Ne supposez jamais qu'une routine IoTimer sera appelée précisément sur une limite d'une seconde car les intervalles à quel tout IoTimer particulier routine est appelée dépend finalement de résolution de l'horloge système.
  47. Ne jamais appeler interfaces de programmation d'application (API) Win32 à partir d'un pilote de périphérique en mode noyau.
  48. Jamais utiliser fonctions récurrentes qui peuvent provoquer la pile pour dépassement de capacité, car l'appelant pile du thread en mode noyau n'augmente pas dynamiquement en cours d'exécution en mode noyau.
  49. N'utilisez jamais pointeurs d'objet interruption (PKINTERRUPT) qui gère plusieurs d'interruption, pour identifier des interruptions dans un ISR dans la mesure où l'adresse de l'objet d'interruption que vous obtenir de l'ISR pas aura toujours identique à celui que vous avez obtenu à partir de IoConnectInterrupt. Vous ne devez utiliser la valeur ServiceContext que vous spécifiez dans IoConnectInterrupt pour identifier le périphérique d'interruption en cours.
  50. Ne jamais décharger un pilote sans effacement CustomTimerDpc (KeCancelTimer). Si le DPC est déclenché une fois que le pilote est déchargé, il pourrait d'accès qui n'existe pas de code et empêcher le système de vérification d'erreur.
  51. Déchargement d'un pilote jusqu'à ce que tous les IRP qui ont le CompletionRoutine e/S du pilote spécifier donné sont jamais terminée. Si l'IRP obtient exécutée par le pilote inférieur une fois que votre pilote est déchargé, le système pourrait tenter d'exécuter le code qui n'existe pas et le système se bloque.
  52. N'activez jamais interruption du périphérique jusqu'à ce que votre pilote soit prêt pour la gérer. Vous devez activer seulement après que votre pilote est complètement initialisé, et ils ne présentent aucun danger pour le système à toucher les structures internes du conducteur dans ISR et DPC.
  53. Jamais d'appel à l'extérieur de votre pilote tout en maintenant un spinlock car il peut provoquer un blocage.
  54. Ne jamais retour tout état autre que STATUS_MORE_PROCESSING_REQUIRED à partir de votre CompletionRoutine e/S pour un IRP créé par votre pilote avec IoBuildAsynchronousFsdRequest/IoAllocateIrp car le paquet IRP n'est pas prêt pour l'achèvement liées post-traitement par le Gestionnaire d'e/S. Tel un IRP doit être libéré explicitement (IoFreeIrp) par le pilote. Si le paquet IRP n'est pas destiné à être réutilisation, il peut être libéré dans le CompletionRoutine avant de renvoyer l'état STATUS_MORE_PROCESSING_REQUIRED.
  55. Jamais d'allouer un IRP avec IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest dans un contexte de thread arbitraire car le IRP reste associé au thread (IRP-> ThreadListEntry) jusqu'à ce qu'il soit libéré.
  56. Ne jamais appeler IoInitializeIrp sur un IRP a été alloué avec IoAllocateIrp avec ChargeQuota paramètre défini sur TRUE. Lorsque vous allouez un IRP avec ChargeQuota défini sur TRUE, le Gestionnaire d'e/S conserve les informations sur le pool à partir de laquelle il la mémoire allouée pour l'IRP en drapeau interne de la Commission de contrôle internationale.

    Lorsque vous appelez IoInitializeIrp sur cet un IRP, les informations de pool d'allocation sont perdues que cette fonction zéros aveuglément l'IRP entière. Cette situation engendre une corruption de la mémoire lorsque vous libérer de l'IRP. En outre, ne jamais réutiliser un IRP provient le Gestionnaire d'e/S. Si vous souhaitez réutiliser un IRP, vous devez allouer votre propre à l'aide de IoAllocateIrp.
  57. Spécifiez jamais WaitMode comme UserMode dans KeWaitForSingleObject/KeWaitForMultipleObjects si l'objet est allouée dans la pile du thread appelant. Corollaire du présent est que si l'objet attendu est créé dans la pile de fonction, vous devez spécifier KernelMode comme WaitMode pour empêcher la paginées en dehors de la pile de thread.
  58. Jamais acquérir des ressources telles que ERESOURCES et FastMutex(Unsafe) dans le contexte d'un thread en mode utilisateur sans protection du code dans une section critique.

    Étant donné que l'acquisition de ces ressources ne déclenche pas l'IRQL pour APC_LEVEL, si le thread est suspendu (effectuée par la mise en file d'attente un APC) après qu'il a acquis la ressource, il pourrait provoquer sécurité du système de blocage et les compromissions. Par conséquent, vous devez acquérir ces ressources soit en déclenchant explicitement l'IRQL APC_LEVEL ou dans une section critique en appelant KeEnterCriticalRegion.

Références

Guide de création de pilote de périphérique MSDN pour Windows NT

Propriétés

Numéro d'article: 186775 - Dernière mise à jour: mardi 27 juillet 2004 - Version: 2.1
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Win32 Device Driver Kit for Windows NT 3.51
  • Microsoft Win32 Device Driver Kit for Windows NT 4.0
Mots-clés : 
kbmt kbinfo KB186775 KbMtfr
Traduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 186775
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.
Exclusion de responsabilité concernant les contenus obsolètes dans la Base de connaissances
Cet article concerne des produits pour lesquels Microsoft n'offre plus de support. Il est par conséquent fourni « en l'état » et ne sera plus mis à jour.

Envoyer des commentaires

 

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