다음을 통해 공유


다중 프로세서 환경의 오류

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 문을 스핀 잠금으로 묶어야 합니다.