Condividi tramite


Errori in un ambiente multiprocessore

Nel sistema operativo basato su NT, i driver sono multithreading; possono ricevere più richieste di I/O da thread diversi contemporaneamente. Nella progettazione di un driver, è necessario presupporre che verrà eseguito in un sistema SMP e adottare le misure appropriate per garantire l'integrità dei dati.

In particolare, ogni volta che un driver modifica i dati dell'oggetto file o globale, deve usare un blocco o una sequenza interlocked per evitare race condition.

Verifica di una race condition quando si fa riferimento a dati specifici dell'oggetto globale o file

Nel frammento di codice seguente può verificarsi una race condition quando il driver accede ai dati globali in 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);

Più thread che immettono questo codice in seguito a una chiamata IOCTL potrebbero causare una perdita di memoria perché il puntatore viene sovrascritto. Per evitare questo problema, il driver deve usare le routine ExInterlocked Xxx o un tipo di blocco quando modifica i dati globali. I requisiti del driver determinano i tipi accettabili di blocchi. Per altre informazioni, vedere Spin Locks, Kernel Dispatcher Objects e ExAcquireResourceSharedLite.

L'esempio seguente tenta di riallocare un buffer specifico del file (Endpoint-LocalAddress>) per contenere l'indirizzo dell'endpoint:

   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);
   }

In questo esempio, una race condition può verificarsi con gli accessi all'oggetto file. Poiché il driver non contiene blocchi, due richieste per lo stesso oggetto file possono immettere questa funzione. Il risultato potrebbe essere un riferimento alla memoria liberata, a più tentativi di liberare la stessa memoria o perdite di memoria. Per evitare questi errori, le due istruzioni if devono essere racchiuse in un blocco di selezione.