INFO: Tipps für Windows NT-Treiber-Entwickler ? Dinge, die verhindern

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 186775 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Alles erweitern | Alles schließen

Zusammenfassung

Folgenden sind einige Tipps zum Erstellen von Windows NT-Gerätetreiber. Die vorgestellten Tipps gelten für alle Technologien. Sie können dies auch als Checkliste zur Problembehandlung für Treiber verwenden.

Benötigen Sie grundlegende Kenntnisse der Windows-Architektur und einige Geräte Treiberentwicklung auftreten, die effektiv unten dargestellten Informationen verwenden. Weitere Informationen zu Treiberentwicklung Gerät finden Sie im Windows NT Gerät Treiber Kit (DDK), das über MSDN Professional-Mitgliedschaft verfügbar ist.

Weitere Informationen

Es folgt eine Liste der Dinge, die Entwickler beim Arbeiten mit Windows NT-Gerätetreiber vermeiden sollten:

  1. Nie zurückgeben STATUS_PENDING über eine Dispatch-Routine ohne markieren das e/A-Anforderungspaket (i/o Request Packet, IRP) ausstehenden (IoMarkIrpPending).
  2. Rufen Sie KeSynchronizeExecution nie ein Interrupt Service Routine (ISR). Es wird das System einen deadlock.
  3. Legen Sie nie wird-> Flags auf DO_BUFFERED_IO und DO_DIRECT_IO. Verwechseln Sie das System und schließlich zu schwerwiegenden Fehler führen kann. Darüber hinaus nie festgelegt METHOD_BUFFERED, METHOD_NEITHER, METHOD_IN_DIRECT oder METHOD_OUT_DIRECT in wird-> Flags, da diese Werte nur beim Definieren von IOCTLs verwendet werden.
  4. Reservieren Sie nie Dispatcher-Objekte aus einem ausgelagerten Pool. Wenn Sie dies tun, wird dies gelegentlich System Bugchecks führen.
  5. Niemals keinen Speicher von ausgelagerten Pool, oder auf Speicher im ausgelagerten Pool während der Ausführung auf IRQL zugreifen > = DISPATCH_LEVEL. Es ist ein schwerwiegender Fehler.
  6. Nie ein Intervall ungleich Null bei IRQL-warten auf ein Kernelobjekt Dispatcher > = DISPATCH_LEVEL. Es ist ein schwerwiegender Fehler.
  7. Nie veranlasst Aufruf alle, die Funktion den aufrufenden Thread um direkt oder indirekt zu warten, während der Ausführung auf IRQL > = DISPATCH_LEVEL. Es ist ein schwerwiegender Fehler.
  8. Nie Verringern des IRQL Interrupt Request Level () unterhalb der Ebene an der obersten Ebene-Routine aufgerufen wurde.
  9. Rufen Sie nie KeLowerIrql() auf, wenn Sie noch nicht KeRaiseIrql() aufgerufen.
  10. Hält Sie nie einen Prozessor (KeStallExecutionProcessor) länger als 50 Mikrosekunden.
  11. Halten Sie niemals alle Spinlocks länger als notwendig. Speichern Sie für eine bessere Gesamtsystemleistung keine systemweiten Spinlocks länger als 25 Mikrosekunden.
  12. Rufen Sie nie KeAcquireSpinLock und KeReleaseSpinLock, KeAcquireSpinLockAtDpcLevel und KeReleaseSpinLockFromDpcLevel, wenn Sie auf DISPATCH_LEVEL größer IRQL ausgeführt.
  13. Freigeben Sie nie ein Spinlock, die vom aufrufenden KeReleaseSpinLockFromDpcLevel mit KeAcquireSpinLock erworben wurde, da die ursprünglichen IRQL nicht wiederhergestellt werden.
  14. Nie Aufrufen von KeAcquireSpinLock und KeReleaseSpinLock oder andere Routine, die eine executive Spinlock aus eine ISR oder SynchCritSection-Routine(s) verwendet.
  15. Vergessen Sie nie DO_DEVICE_INITIALIZING Flag deaktivieren, wenn Sie ein Gerät-Objekt in einer Routine außer DriverEntry erstellen.
  16. Die nie Warteschlange ein deferred Procedure-Aufruf (DPC)-Objekt (mit KeInsertQueueDpc) mit mehreren Threads auf unterschiedlichen Prozessoren gleichzeitig. Es kann zu schwerwiegenden Fehler führen.
  17. Deallocate nie einen periodischen Zeitgeber aus eine CutomerTimerDPC-Routine. Sie können aus einer DPC-Routine nicht periodischer Zeitgeber freigeben.
  18. Nie Zeiger des gleichen DPC an KeSetTimer oder KeSetTimerEx übergeben (CustomTimerDpc) und KeInsertQueueDpc (CustomDpc), da er bewirkt, dass Racebedingungen.
  19. Nie Aufruf IoStartNextPacket ein Spinlock halten. Sie können Ihr System deadlock.
  20. Nie Aufruf IoCompleteRequest halten ein Spinlock. Sie können Ihr System deadlock.
  21. Rufen Sie nie IoCompleteRequest, ohne die Fertigstellung-Routine auf NULL festlegen, wenn der Treiber die Fertigstellung-Routine festgelegt.
  22. Vergessen Sie nie den e/a-Status-Block in das IRP vor dem Aufruf IoCompleteRequest festgelegt.
  23. Rufen Sie IoMarkPending nie nach queuing ein IRP oder an einen anderen Treiber (IoCallDriver) zu senden. Das IRP kann abgeschlossen werden, bevor der Treiber IoMarkPending ruft und eine Fehlerüberprüfung auftreten. Für Treiber mit Abschluss Routinen müssen Abschluss Routinen IoMarkPending aufrufen, wenn-> PendingReturned Irp festgelegt ist.
  24. Berühren Sie nie eine IRP nachdem IoCompleteRequest davon aufgerufen haben.
  25. Rufen Sie IoCancelIrp nie auf eine IRP, die nicht Ihren Treiber gehört, wenn Sie wissen, dass das IRP noch nicht abgeschlossen wurde.
  26. Rufen Sie IoCancelIrp nie für IRP, das auf Dispatch-Routine funktioniert, bis Ihre Dispatch-Routine an Aufrufer zurückgegeben.
  27. Rufen Sie nie IoMakeAssociatedIrp IRPs für niedrigere Treiber von einem intermediate-Treiber zu erstellen. Das IRP Sie in der intermediate-Treiber erhalten konnte einen zugeordneten IRP sein, und Sie können nicht andere IRPs zu einer bereits zugeordneten IRP zuordnen.
  28. Nie gepuffert Aufruf IoMakeAssociatedIrp auf einer IRP, die zum Ausführen eingerichtet ist, e/A.
  29. Nie einfach Dereferenzieren Sie virtuellen Zeiger auf Gerät e/a-Register und greifen Sie darauf . Verwenden Sie immer korrekte Hardware Abstraktionsschicht (Layer, HAL) Funktionen, um ein Gerät zugreifen.
  30. Rufen Sie nie Objektfelder IRP ANZEIGT oder Gerät aus eine ISR, die von DISPATCH_LEVEL geändert werden kann. Auf einem Multiprozessorsystem symmetrischen kann dies zur Beschädigung von Daten führen.
  31. Ändern Sie Daten nie bei hohen IRQL ausgeführt wird, wenn die Daten von Low-IRQL Code geschrieben werden können. Verwenden Sie die KeSynchronizeExecution-Routine.
  32. Nie erwerben eines des Treibers-Spinlocks (Wenn Sie einen verfügen) in Ihrer Routine DispatchCleanup vor dem systemweiten Abbrechen Drehfeld Sperre (IoAcquireCancelSpinLock). Eine konsistente Sperre Anschaffung Hierarchie während der Treiber folgende unbedingt potenzielle Deadlocks vermeiden.
  33. Aufruf IoAcquireCancelSpinLock in die Abbrechen-Routine da immer mit dem System heißt Spinlock Abbrechen nie auf dessen Auftrag gehalten.
  34. Vergessen Sie nie IoReleaseCancelSpinLock aufrufen, bevor von einer Routine auf "Abbrechen".
  35. Verwenden Sie niemals IRQL-basierten Synchronisierung, da dies nur auf Prozessor-Systemen funktioniert. Auslösen IRQL auf einem Prozessor Interrupts auf dem anderen Prozessoren nicht maskieren.
  36. Verwenden Sie niemals RtlCopyMemory für überlappende Speicheradressbereiche. Verwendung RtlMoveMemory.
  37. Nie genommen Sie Seitengrößen sogar für einen bestimmten Prozessor konstant sind an. Verwendung PAGE_SIZE und andere Seite Verwandte Konstanten in Headerdateien Portabilität verwalten definiert.
  38. Greifen Sie alle Registrierungsschlüssel außer Registry\Machine\Hardware und Registry\Machine\System auf nie DriverEntry eines Treibers in Phase Boot\System Initialisierung geladen .
  39. Erstellen Sie nie einen Enum-Schlüssel für das Laden eines Treibers einen Treiber-Registrierungsschlüssel (Registry\Machine\System\CurrentControlSet\Services). Das System wird dieser Schlüssel dynamisch erstellt.
  40. Nie Kanal und Anschluss Versuch, ein physisches Gerät zu initialisieren, ohne Inanspruchnahme der erforderlichen Bus relativ e/a-Ports, Speicher Bereiche, Interrupt oder direkter Speicherzugriff (DMA) Hardware-Ressourcen in der Registrierung zunächst.
  41. Rufen Sie IoRegisterDriverReinitialization nie Ihre DriverEntry Routine, sofern gibt STATUS_SUCCESS zurück.
  42. Nie rufen Sie KeSetEvent mit dem Parameter Wait auf TRUE aus einer navigierbaren Thread oder auslagerungsfähigen Treiber Routine, die bei IRQL PASSIVE_LEVEL ausgeführt wird. Diese Art von Aufruf führt einen schwerwiegende Seitenfehler, wenn eine Routine geschieht zwischen den Aufrufen von KeSetEvent und KeWait ausgelagert werdenObjekt(e).
  43. Nie rufen Sie KeReleaseSemaphore mit dem Parameter Wait auf TRUE aus einer navigierbaren Thread oder auslagerungsfähigen Treiber Routine, die bei IRQL PASSIVE_LEVEL ausgeführt wird. Wenn eine Routine geschieht zwischen den Aufrufen von KeReleaseSemaphore und KeWait ausgelagert werdenObjekt(e), diesem Anruftyp schwerwiegende Seitenfehler verursacht.
  44. Nie rufen Sie KeReleaseMutex mit dem Parameter Wait auf TRUE aus einer navigierbaren Thread oder auslagerungsfähigen Treiber Routine, die bei IRQL PASSIVE_LEVEL ausgeführt wird. Wenn eine Routine geschieht zwischen den Aufrufen von KeReleaseMutex und KeWait ausgelagert werdenObjekt(e), diesem Anruftyp schwerwiegende Seitenfehler verursacht.
  45. Nie einen Treiber für Verkaufsversionen von Windows NT down the System bringen rufen KeBugCheckEx oder KeBugCheck, sofern der Fehler ist ein schwerwiegender Fehler der Systemspeicher beschädigt oder bewirken, dass schließlich das System Fehlerüberprüfung würde. Versuchen Sie immer um Fehlerbedingungen ordnungsgemäß behandeln.
  46. Nie davon aus, eine Routine IoTimer präzise an einer Grenze einer Sekunde aufgerufen wird, da die Intervalle auf dem bestimmten IoTimer Routine aufgerufen wird letztendlich Auflösung der Systemuhr abhängt.
  47. Rufen Sie Win32s Anwendungsprogrammierschnittstellen (APIs) nie ein Kernelmodus-Gerätetreiber.
  48. Nie verwenden rekursive Funktionen, die im Stapel überläuft, weil den aufrufenden Stapel des Threads Kernel-Modus nicht dynamisch vergrößert wird, während der Ausführung im Kernelmodus verursachen können.
  49. Verwenden Sie niemals Interrupt-Objektzeigern (PKINTERRUPT), die mehr als ein Interrupt behandelt Interrupts in eine ISR identifizieren, da die Adresse der Interrupt-Objekts Sie in der ISR erhalten nicht immer identisch mit der wird aus IoConnectInterrupt haben. Sie sollten nur die ServiceContext-Wert, den Sie im IoConnectInterrupt angeben verwenden zum Identifizieren des aktuellen interrupting Geräts.
  50. Nie Entladen eines Treibers ohne deaktivieren CustomTimerDpc (KeCancelTimer). Wenn die DPC ausgelöst wird, nachdem der Treiber entladen wurde, konnte es nicht vorhanden-Code erreicht und bewirken, dass das System Fehlerüberprüfung.
  51. Entladen eines Treibers bis alle IRPs, die e/A-CompletionRoutine des Treibers in es festgelegt werden nie abgeschlossen. Wenn das IRP durch den niedrigeren Treiber abgeschlossen Ruft ab, nach dem Entladen des Treibers, könnte das System versuchen, den nicht vorhandene-Code ausführen und bewirken, dass das System Absturz.
  52. Aktivieren Sie Gerät Interrupt nie, bis der Treiber zur Verarbeitung bereit ist. Sie sollten erst nach dem der Treiber vollständig initialisiert wurde und für das System ist zu berühren des Treibers interne Strukturen in ISR und DPCS sicher aktivieren.
  53. Nie Aufruf außerhalb des Treibers eine Sperrvariable halten, da dies zu Deadlocks führen kann.
  54. Alle anderen Status als STATUS_MORE_PROCESSING_REQUIRED aus der e/a-CompletionRoutine für eine IRP vom Treiber mit IoBuildAsynchronousFsdRequest-IoAllocateIrp erstellt, da das IRP nicht für die Vervollständigung vorbereitet ist Zusammenhang nie zurückgeben Nachbearbeitung durch den e/A-Manager. Eine solche IRP sollte explizit freigegeben werden (IoFreeIrp) durch den Treiber. Wenn das IRP nicht für die Wiederverwendung vorgesehen ist, können Sie in der CompletionRoutine vor der Rückgabe Status STATUS_MORE_PROCESSING_REQUIRED freigegeben werden.
  55. Nie eine IRP mit IoBuildSynchronousFsdRequest-IoBuildDeviceIoControlRequest in einem Threadkontext willkürlichen reservieren, da das IRP (-> ThreadListEntry Irp)-Thread zugeordnet bleibt bis es freigegeben wird.
  56. Rufen Sie IoInitializeIrp nie auf einen mit IoAllocateIrp reserviert wurde IRP mit ChargeQuota-Parameter auf TRUE festgelegt. Wenn Sie eine IRP ChargeQuota auf TRUE festgelegt zuordnen, behält der e/A-Manager die Informationen über den Pool aus dem der Speicher für das IRP in das IRP internes Flag zugewiesen.

    Beim Aufrufen von IoInitializeIrp für eine solche IRP sind die Reservierung Pool Informationen verloren gehen, wie diese Funktion das gesamte IRP Blind Nullen. Dies führt zu einer Speicherbeschädigung, wenn Sie das IRP freigeben. Darüber hinaus nie Wiederverwendung einer IRP, die aus der e/A-Manager. Wenn Sie eine IRP wiederverwenden möchten, sollten Sie Ihre eigenen reservieren mithilfe von IoAllocateIrp.
  57. Geben Sie WaitMode nie als Benutzermodus in KeWaitForSingleObject-KeWaitForMultipleObjects, wenn das Objekt im Stapel den aufrufenden Thread zugeordnet ist. Corollary dieser ist, wenn das Objekt auf gewartet wird in der Aufrufliste Funktion erstellt wird, Sie KernelMode als WaitMode verhindern, dass die Threadstapel ausgelagert wird angeben müssen.
  58. Erwerben Sie nie Ressourcen wie z. B. ERESOURCES und FastMutex(Unsafe) im Kontext eines Benutzermodus-Threads ohne den Code in einen kritischen Abschnitt geschützt.

    Da die Anschaffung von diesen Ressourcen keine IRQL, APC_LEVEL, ausgelöst wird, wenn der Thread unterbrochen wird (durch eine APC queuing durchgeführt) Nachdem Sie die Ressource erworben hat, bewirken Sie Deadlock und Gefährdung der Systemsicherheit. Daher sollten Sie solche Ressourcen entweder durch explizit Auslösen der IRQL APC_LEVEL oder in einen kritischen Abschnitt erwerben, durch Aufrufen von KeEnterCriticalRegion.

Informationsquellen

MSDN Geräte Treiber Design-Handbuch für Windows NT

Eigenschaften

Artikel-ID: 186775 - Geändert am: Dienstag, 27. Juli 2004 - Version: 2.1
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Win32 Device Driver Kit für Windows NT 3.51
  • Microsoft Win32 Device Driver Kit für Windows NT 4.0
Keywords: 
kbmt kbinfo KB186775 KbMtde
Maschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 186775
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.
Disclaimer zu nicht mehr gepflegten KB-Inhalten
Dieser Artikel wurde für Produkte verfasst, für die Microsoft keinen Support mehr anbietet. Der Artikel wird deshalb in der vorliegenden Form bereitgestellt und nicht mehr weiter aktualisiert.

Ihr Feedback an uns

 

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