資訊: 秘訣對於 Windows NT 驅動程式開發人員--避免的事情

文章翻譯 文章翻譯
文章編號: 186775 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

結論

下面是建立 Windows NT 裝置驅動程式的一些秘訣。所呈現的秘訣將套用到所有的技術。您也可以使用這作為檢查清單來疑難排解驅動程式問題。

您必須有 Windows NT 架構的基本知識和經驗使用有效地提出以下的資訊某些裝置驅動程式開發。如需有關裝置驅動程式開發的詳細資訊,請參閱 Windows NT 裝置驅動程式套件 (DDK) 這是可透過 MSDN 專業成員資格。

其他相關資訊

以下為清單的開發人員應該避免使用 Windows NT 裝置驅動程式時的事項:

  1. 永遠不會傳回從分派路由,而不將 I/O 要求封包 (IRP) 標示擱置 (IoMarkIrpPending) STATUS_PENDING。
  2. 永遠不會呼叫 KeSynchronizeExecution 從插斷服務常式 (ISR)。它會鎖死您的系統。
  3. 永遠不會設定為同時 DO_BUFFERED_IO 和 DO_DIRECT_IO DeviceObject-> [旗標。 它可以混淆系統,最後導致嚴重的錯誤。而且,永遠不會設定 METHOD_BUFFERED、 METHOD_NEITHER、 METHOD_IN_DIRECT 或 METHOD_OUT_DIRECT DeviceObject-標幟,> 中因為這些值只用於定義 IOCTLs。
  4. 永遠不會從分頁集區配置發送器物件。如果您這麼做,它會造成偶爾系統 bugchecks。
  5. 永遠不會從分頁集區配置記憶體或存取記憶體分頁集區中的同時執行的 IRQL > = DISPATCH_LEVEL。它是一個嚴重的錯誤。
  6. 永遠不會等待核心發送器物件上非零間隔 IRQL > = DISPATCH_LEVEL。它是一個嚴重的錯誤。
  7. 永遠不會呼叫任何函式,會導致等候 IRQL 在執行時直接或間接呼叫的執行緒 > = DISPATCH_LEVEL。它是一個嚴重的錯誤。
  8. 永遠不會降低插斷要求等級 (IRQL) 低於層級處已經被叫用您最上層的例行工作。
  9. 如果您還沒有呼叫 KeRaiseIrql(),永遠不會呼叫 KeLowerIrql()。
  10. 永遠不會延後一處理器 (KeStallExecutionProcessor) 長度大於 50 的微秒數。
  11. 永遠不會保留任何長度超過所需的微調鎖定。以較佳整體系統效能嗎不保留任何全系統微調鎖定超過 25 的微秒數。
  12. 永遠不會呼叫 KeAcquireSpinLock 和 KeReleaseSpinLock,或 KeAcquireSpinLockAtDpcLevel KeReleaseSpinLockFromDpcLevel,IRQL 大於 DISPATCH_LEVEL 在執行時。
  13. 因為將不會還原原始的 IRQL,永遠不會釋放呼叫 KeReleaseSpinLockFromDpcLevel 取得與 KeAcquireSpinLock 的微調鎖定。
  14. 永遠不會呼叫 KeAcquireSpinLock 和 KeReleaseSpinLock 或任何其他使用從 ISR 或 SynchCritSection routine(s) 的主管微調鎖定的常式。
  15. 永遠不會忘了清除 DO_DEVICE_INITIALIZING 旗標,當以外 DriverEntry 常式中建立裝置物件。
  16. 永遠不會同時與多個執行緒上不同的處理器佇列 (使用 KeInsertQueueDpc) 的延緩的程序呼叫 (DPC) 物件。它可能會導致嚴重的錯誤。
  17. 永遠不會解除配置從 CutomerTimerDPC 常式定期計時器。 您可以解除配置從 DPC 常式 nonperiodic 計時器。
  18. 永遠不會將相同的 DPC 指標傳遞至 KeSetTimer 或 KeSetTimerEx (CustomTimerDpc) 和 KeInsertQueueDpc (CustomDpc) 因為它會造成競爭情形。
  19. 永遠不會呼叫 IoStartNextPacket 按住微調鎖定。它可以鎖死您的系統。
  20. 永遠不會呼叫 IoCompleteRequest 按住微調鎖定。它可以鎖死您的系統。
  21. 永遠不會呼叫 IoCompleteRequest 而不完成常式設定為 NULL,如果您的驅動程式設定完成常式。
  22. 永遠不會忘了呼叫 IoCompleteRequest 之前,在 [IRP 設定 I/O 狀態區塊。
  23. 永遠不會呼叫 IoMarkPending 佇列的 IRP,或將它傳送到另一個驅動程式 (IoCallDriver) 之後。[IRP 可能驅動程式會呼叫 IoMarkPending 和錯誤檢查,可能會發生之前完成。與完成常式的驅動程式完成常式必須呼叫 IoMarkPending 如果 Irp-PendingReturned > 設定。
  24. 永遠不會碰觸的 IRP 之後您已經在其上呼叫 IoCompleteRequest。
  25. 永遠不會呼叫 IoCancelIrp 上不屬於您的驅動程式除非您知道 [IRP 尚未尚未完成的 IRP。
  26. 永遠不會呼叫直到分派常式傳回給呼叫端,投入分派常式的 IRP IoCancelIrp。
  27. 永遠不會呼叫 IoMakeAssociatedIrp 建立 IRP 較低的驅動程式從中繼驅動程式。您在中間的驅動程式中取得的 IRP 找一個相關聯的 IRP,並且您無法建立關聯已經相關聯的 IRP 其他 IRP。
  28. 永遠不會呼叫上設定為執行的 IRP IoMakeAssociatedIrp 緩衝 I/O。
  29. 永遠不只是取值裝置 I/O 暫存器的虛擬指標及存取它們。永遠使用正確的硬體抽象層 (HAL) 函式來存取裝置。
  30. 永遠不會從可能修改 DISPATCH_LEVEL 從一個 ISR 存取 IRP 或裝置的 [物件] 欄位。對稱式多處理器系統上這可能會造成資料損毀。
  31. 永遠不會執行在高 IRQL,如果該資料可能會寫入由低 IRQL 程式碼時修改資料。使用 KeSynchronizeExecution 常式。
  32. 永遠不會取得其中一個驅動程式自己的微調鎖定 (如果有任何) 中您 DispatchCleanup 例行工作前取得整個系統取消微調鎖定 (IoAcquireCancelSpinLock)。遵循一致的鎖定擷取階層整個驅動程式是以避免潛在的死結不可或缺的。
  33. 永遠不會在 [取消] 常式 IoAcquireCancelSpinLock 因為使用系統永遠呼叫取消微調鎖定的呼叫持有代表它執行。
  34. 永遠不會忘記要從 [取消] 常式傳回之前,先呼叫 IoReleaseCancelSpinLock。
  35. 永遠不會使用 IRQL 為基礎的同步處理,因為這適用於只在單一處理器系統上。在一個處理器上引發 IRQL 並遮罩其他處理器上的插斷。
  36. 永遠不會使用 RtlCopyMemory 重疊的記憶體位址範圍。使用 RtlMoveMemory。
  37. 絕對不要假設的頁面大小是常數即使針對給定的 CPU。使用 PAGE_SIZE 和其他頁來維護可攜性的標頭檔中定義的相關的常數。
  38. 永遠不會從 DriverEntry 常式 Boot\System 初始化階段中載入的驅動程式的存取 Registry\Machine\Hardware 和 Registry\Machine\System 以外的任何登錄機碼。
  39. 永遠不會建立載入驅動程式的登錄機碼 (Registry\Machine\System\CurrentControlSet\Services) 下驅動程式的列舉鍵。系統會以動態方式建立此機碼。
  40. 永遠不會嘗試初始化不必要的匯流排相對 I/O 連接埠、 記憶體範圍、 插斷或直接記憶體存取 (DMA) 所宣告的實體裝置頻道/連接埠在登錄中的硬體資源第一次。
  41. 永遠不會從您 DriverEntry 呼叫 IoRegisterDriverReinitialization 例行除非它會傳回 STATUS_SUCCESS。
  42. 永遠不會從可分頁的執行緒或 IRQL PASSIVE_LEVEL 在執行的可分頁的驅動程式常式呼叫 Wait 參數設定為 TRUE KeSetEvent。如果您的例行工作剛好 KeSetEvent 對呼叫與 KeWait 之間移出此類呼叫會造成嚴重的分頁錯誤個物件。
  43. 永遠不會從可分頁的執行緒或 IRQL PASSIVE_LEVEL 在執行的可分頁的驅動程式常式呼叫 Wait 參數設定為 TRUE KeReleaseSemaphore。如果您的例行工作剛好移出 KeReleaseSemaphore 對呼叫與 KeWait 之間object(s) 這種類型的呼叫會造成嚴重的分頁錯誤。
  44. 永遠不會從可分頁的執行緒或 IRQL PASSIVE_LEVEL 在執行的可分頁的驅動程式常式呼叫 Wait 參數設定為 TRUE KeReleaseMutex。如果您的例行工作剛好移出 KeReleaseMutex 對呼叫與 KeWait 之間object(s) 這種類型的呼叫會造成嚴重的分頁錯誤。
  45. 永遠不會從零售版的 Windows NT 驅動程式,以關閉系統呼叫 KeBugCheckEx 或 KeBugCheck,除非遇到此錯誤是嚴重的錯誤會損毀的系統記憶體或最後會導致錯誤檢查的系統。永遠試著依正常程序處理錯誤情況。
  46. 絕對不要假設在一秒的界限上精確地會呼叫 IoTimer 常式,因為在哪一個任何特定 IoTimer 呼叫常式間隔最終取決於系統時鐘的解析度。
  47. 永遠不會呼叫 Win32s 應用程式發展介面 (API) 從核心模式裝置驅動程式。
  48. 永遠不會使用遞迴函式可能會造成堆疊溢位因為核心模式中執行時不動態地成長呼叫的執行緒核心模式堆疊。
  49. 因為您在 ISR 中取得的插斷物件的位址不一定會從 IoConnectInterrupt 取得的一個相同,永遠不會使用來識別一個 ISR 的插斷插斷物件指標 (PKINTERRUPT) 處理多個插斷。您應該只使用您指定中 IoConnectInterrupt ServiceContext 值來識別目前 interrupting 裝置。
  50. 永遠不會卸載驅動程式而不清除 CustomTimerDpc (KeCancelTimer)。 如果驅動程式卸載之後,就會引發 [DPC,它,可以叫用非存在程式碼,會導致錯誤檢查的系統。
  51. 永遠不會卸載驅動程式有 I/O CompletionRoutine 的驅動程式設定在它的所有 IRP 才會完成。如果 [IRP 取得由較低的驅動程式已完成的驅動程式卸載之後,系統可以嘗試執行不存在的程式碼,並造成系統當機。
  52. 永遠不會啟用裝置插斷,直到您的驅動程式為準備好處理它。 您應該在完全初始化您的驅動程式時,而且很安全系統碰觸 ISR 和 DPC 中的驅動程式的內部結構之後,才啟用。
  53. 外部的驅動程式在保留一個 spinlock,因為它會造成死結時永遠不會呼叫。
  54. 永遠不會傳回從 IoBuildAsynchronousFsdRequest/IoAllocateIrp 與您驅動程式所建立,因為 [IRP 尚未準備就緒以完成的 IRP 您 I/O CompletionRoutine STATUS_MORE_PROCESSING_REQUIRED 以外的其他任何狀態相關的 I/O 經理的後續處理。這類的 IRP 應該明確釋放 (IoFreeIrp) 由驅動程式。如果 [IRP 不是供重複使用,它可以被釋放之 CompletionRoutine 中傳回狀態 STATUS_MORE_PROCESSING_REQUIRED 之前。
  55. 永遠不會配置在任意執行緒的內容與 IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest IRP,因為 [IRP 維持執行緒 (-> [ThreadListEntry Irp) 相關聯直到它被釋放。
  56. 永遠不會呼叫上已配置與 IoAllocateIrp 的 IRP IoInitializeIrp ChargeQuota 參數設定為 TRUE。當您配置 ChargeQuota 設定為 TRUE IRP 時,I/O 管理員會保留它可以從中配置記憶體來 IRP IRP 的內部旗標中的集區的相關資訊。

    當您在這類的 IRP 上呼叫 IoInitializeIrp 時,為此函式盲目零的整個 IRP 配置集區資訊都會遺失。 這會導致記憶體損毀時您釋放 [IRP。 而且,永遠不會重複使用來自 IO 管理員的 IRP]。如果想重複使用的 IRP 您應該配置您自己使用 IoAllocateIrp。
  57. 如果在 [物件配置呼叫的執行緒堆疊中,永遠不會指定為在 KeWaitForSingleObject/KeWaitForMultipleObjects UserMode WaitMode。這個 corollary 是如果等候物件在函式堆疊中建立的您必須指定 KernelMode 為以防止執行緒堆疊移出 WaitMode。
  58. 永遠不會取得資源 (例如 ERESOURCES 和 FastMutex(Unsafe) 使用者模式執行緒的內容中不含保護關鍵區段中的程式碼。

    因為這些資源擷取不會引發至 APC_LEVEL,IRQL,如果執行緒暫止 (由佇列的 APC 完成) 已取得資源後可能會導致死結和危害系統安全性。因此,您應該呼叫 KeEnterCriticalRegion],以取得這類資源無論是藉由明確引發 IRQL APC_LEVEL 或在關鍵區段。

?考

Windows NT 的 MSDN 裝置驅動程式的設計指南

屬性

文章編號: 186775 - 上次校閱: 2004年7月27日 - 版次: 2.1
這篇文章中的資訊適用於:
  • Microsoft Win32 Device Driver Kit for Windows NT 3.51
  • Microsoft Win32 Device Driver Kit for Windows NT 4.0
關鍵字:?
kbmt kbinfo KB186775 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:186775
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。
依現狀不再更新的知識庫內容免責聲明
本文旨在說明 Microsoft 不再提供支援的產品。因此,本文係依「現狀」提供,不會再更新。

提供意見

 

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