共用方式為


多處理器環境中的錯誤

在 NT 型作業系統上,驅動程式是多執行緒的;他們可以同時接收來自不同執行緒的多個 I/O 要求。 在設計驅動程式時,您必須假設它會在 SMP 系統上執行,並採取適當的措施以確保資料完整性。

具體而言,每當驅動程式變更全域或檔案物件資料時,都必須使用鎖定或相互鎖定序列來防止競爭狀況。

參考全域或檔案物件特定資料時遇到競爭狀況

在下列程式碼片段中,當驅動程式存取 Data.LpcInfo的全域資料時,可能會發生競爭狀況:

   PLPC_INFO pLpcInfo = &Data.LpcInfo; //Pointer to global data
   ...
   ...
   // This saved pointer may be overwritten by another thread.
   pLpcInfo->LpcPortName.Buffer = ExAllocatePool(
                                     PagedPool,
                                     arg->PortName.Length);

由於 IOCTL 呼叫而輸入此程式碼的多個執行緒,可能會導致記憶體流失,因為會覆寫指標。 若要避免這個問題,驅動程式應該在變更全域資料時,使用ExInterlockedXxx常式或某種類型的鎖定。 驅動程式的需求會決定可接受的鎖定類型。 如需詳細資訊,請參閱 微調鎖定核心發送器物件ExAcquireResourceSharedLite

下列範例會嘗試重新配置檔案特定的緩衝區, (Endpoint-LocalAddress >) 來保存端點位址:

   Endpoint = FileObject->FsContext;

    if ( Endpoint->LocalAddress != NULL &&
         Endpoint->LocalAddressLength <
                   ListenEndpoint->LocalAddressLength ) {

      FREE_POOL (Endpoint->LocalAddress,
                 LOCAL_ADDRESS_POOL_TAG
                 );
      Endpoint->LocalAddress  = NULL;
   }

    if ( Endpoint->LocalAddress == NULL ) {
       Endpoint->LocalAddress =
            ALLOCATE_POOL (NonPagedPool,
                           ListenEndpoint->LocalAddressLength,
                           LOCAL_ADDRESS_POOL_TAG);
   }

在此範例中,可能會有存取檔案物件的競爭狀況。 因為驅動程式不會保留任何鎖定,所以相同檔案物件的兩個要求可以進入此函式。 結果可能是釋放記憶體的參考、多次嘗試釋放相同的記憶體,或記憶體流失。 若要避免這些錯誤,兩個 if 語句應該以微調鎖定括住。