驅動程式時應當避免的事項列表

來源:互聯網
上載者:User

下面是開發人員在使用 Windows NT 裝置驅動程式時應當避免的事項列表: 

1. 一定不要在沒有標註 I/O 請求資料包 (IRP) 掛起 (IoMarkIrpPending) 的情況下通過調度常式返回 STATUS_PENDING。 
2. 一定不要通過插斷服務常式 (ISR) 調用 KeSynchronizeExecution。 它會使系統死結。 
3. 一定不要將 DeviceObject->Flags 設定為 DO_BUFFERED_IO 和 DO_DIRECT_IO。 它會擾亂系統並最終導致致命錯誤。 而且,一定不要在 DeviceObject->Flags 中設定 METHOD_BUFFERED、METHOD_NEITHER、METHOD_IN_DIRECT 或 METHOD_OUT_DIRECT,因為這些值只在定義 IOCTL 時使用。 
4. 一定不要通過頁面緩衝池分配發送器對象。 如果這樣做,將會偶爾導致系統故障檢測 (Bugcheck)。 
5. 當運行於 IRQL >= DISPATCH_LEVEL 時,一定不要通過頁面緩衝池分配記憶體,或訪問頁面緩衝池中的記憶體。 這是一個致命錯誤。 
6. 一定不要在 IRQL >= DISPATCH_LEVEL 上等候核心發送器對象出現非零間隔。 這是一個致命錯誤。 
7. 在 IRQL >= DISPATCH_LEVEL 上執行時,一定不要調用任何導致調用線程發生直接或間接等待的函數。 這是一個致命錯誤。 
8. 一定不要把插斷要求層級 (IRQL) 降低到低於您的頂級常式被調用的層級。 
9. 如果沒有調用過 KeRaiseIrql(),則一定不要調用 KeLowerIrql()。 

10. 一定不要使處理器 (KeStallExecutionProcessor) 停止運轉的時間超過 50 微秒。 
11. 一定不要使旋轉鎖 (Spin Lock) 保持鎖定狀態的時間超過您的需要。 要使系統獲得更好的總體效能,請不要使任何系統範圍內有效旋轉鎖的鎖定時間超過 25 微秒。 
12. 當 IRQL 大於 DISPATCH_LEVEL 時,一定不要調用 KeAcquireSpinLock 和 KeReleaseSpinLock,或 KeAcquireSpinLockAtDpcLevel 和 KeReleaseSpinLockFromDpcLevel。 
13. 一定不要通過調用 KeReleaseSpinLockFromDpcLevel 來釋放 KeAcquireSpinLock 所擷取的旋轉鎖,因為這會使原始 IRQL 無法被還原。 
14. 一定不要在 ISR 或 SynchCritSection 常式中調用 KeAcquireSpinLock 和 KeReleaseSpinLock 或者其它任何使用可執行旋轉鎖的常式。 
15. 當您在常式中而不是在 DriverEntry 中建立裝置對象時,一定不要忘記清除 DO_DEVICE_INITIALIZING 標記。 
16. 一定不要同時在不同處理器的多個線程中將延時程序呼叫 (DPC) 對象添加到隊列中(使用 KeInsertQueueDpc)。 這會導致致命錯誤。 
17. 一定不要通過 CutomerTimerDPC 常式釋放周期定時器。 您可以通過 DPC 常式釋放非周期定時器。 
18. 一定不要將相同的 DPC 指標傳遞給 KeSetTimer,或者 KeSetTimerEx (CustomTimerDpc) 和 KeInsertQueueDpc (CustomDpc),因為這將導致競爭。 
19. 旋轉鎖鎖定時,一定不要調用 IoStartNextPacket。 這將使系統死結。 
20. 旋轉鎖鎖定時,一定不要調用 IoCompleteRequest。 這將使系統死結。 
21. 如果您的驅動程式設定了完成常式,那麼一定不要在沒有把完成常式設定為 NULL 的情況下調用 IoCompleteRequest。 
22. 調用 IoCompleteRequest 之前,一定不要忘記設定 IRP 中的 I/O 狀態區。 
23. 在將 IRP 添加到隊列中或將它發送到另一個驅動程式 (IoCallDriver) 之後,一定不要調用 IoMarkPending。 在驅動程式調用 IoMarkPending 之前,IRP 可能已經完成,由此可能發生故障檢測。 對於包含完成常式的驅動程式,如果設定了 Irp->PendingReturned,則完成常式必須調用 IoMarkPending。 
24. 一定不要在已經對某個 IRP 調用 IoCompleteRequest 之後再去訪問該 IRP。 
25. 一定不要對不屬於您的驅動程式的 IRP 調用 IoCancelIrp,除非您知道該 IRP 還沒有完成。 
26. 在您的調度常式返回到調用者之前,一定不要對您的調度常式正在處理的 IRP 調 

55. 一定不要在任意的線程上下文 中使用 IoBuildSynchronousFsdRequest/IoBuildDeviceIoControlRequest 來分配 IRP,因為該 IRP 依然與該線程保持關聯 (Irp->ThreadListEntry),直到它被釋放。 
56. 如果已經使用 IoAllocateIrp 在 ChargeQuota 參數被設定為 TRUE 的情況下分配了某個 IRP,那麼一定不要對該 IRP 調用 IoInitializeIrp。 如果在 ChargeQuota 設定為 TRUE 的情況下分配 IRP,則 I/O 管理器將把它為該 IRP 分配記憶體時所用的緩衝池的相關資訊儲存在該 IRP 的內部標記中。 

如果對這樣的 IRP 調用 IoInitializeIrp,那麼,當該函數盲目地清零整個 IRP 時,分配池資訊將會丟失。 當您釋放 IRP 時,這將導致記憶體被破壞。 同時,一定不要重用來自 IO 管理器的 IRP。 如果要重用 IRP,應當使用 IoAllocateIrp 分配您自己的 IRP。 
57. 如果在調用線程的堆棧中分配 了對象,就一定不要在 KeWaitForSingleObject/KeWaitForMultipleObjects 中將 WaitMode 指定為 UserMode。 這樣做的結果是,如果被等候的對象是在函數堆棧中建立的,那麼您必須將 WaitMode 指定為 KernelMode 才能防止線程被頁面調度出去。 
58. 在沒有對關鍵節中的代碼加以保護的情況下,一定不要在使用者模式線程的上下文中擷取諸如 ERESOURCES 和 FastMutex(Unsafe) 這類資源。 

因為擷取這些資源不會使 IRQL 提高到 APC_LEVEL,所以,如果線程在已擷取資源後被掛起(通過將 APC 排入佇列實現),它可能導致死結,並使系統安全性降低。 因此,應當通過顯式地將 IRQL 提高到 APC_LEVEL,或者調用 KeEnterCriticalRegion 來進入關鍵段,然後可以擷取這些資源。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.