Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В операционной системе на основе NT драйверы многопоточные; они могут одновременно получать несколько запросов ввода-вывода из разных потоков. При разработке драйвера необходимо предположить, что он будет выполняться в системе 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 должны быть заключены в спиновую блокировку.