UMDF 1.x 드라이버에서 데이터 버퍼 액세스
경고
UMDF 2는 UMDF의 최신 버전이며 UMDF 1을 대체합니다. 모든 새 UMDF 드라이버는 UMDF 2를 사용하여 작성해야 합니다. UMDF 1에 새 기능이 추가되지 않으며 최신 버전의 Windows 10 UMDF 1에 대한 지원이 제한됩니다. 유니버설 Windows 드라이버는 UMDF 2를 사용해야 합니다.
자세한 내용은 UMDF를 사용하여 시작 참조하세요.
UMDF 2의 데이터 버퍼에 액세스하는 방법에 대한 자세한 내용은 WDF 드라이버에서 데이터 버퍼 액세스를 참조하세요.
드라이버가 읽기, 쓰기 또는 디바이스 I/O 제어 요청을 받으면 요청 개체에 입력 버퍼 또는 출력 버퍼 또는 둘 다 포함됩니다. (몇 가지 디바이스 I/O 컨트롤 요청은 두 개의 입력, 두 개의 출력 또는 두 개의 입력/출력 버퍼를 제공합니다.)
입력 버퍼에는 드라이버에 필요한 정보가 포함됩니다. 쓰기 요청의 경우 일반적으로 이 정보는 함수 드라이버가 디바이스에 보내야 하는 데이터입니다. 디바이스 I/O 컨트롤 요청의 경우 입력 버퍼에 드라이버가 수행해야 하는 작업 유형을 나타내는 정보가 포함될 수 있습니다.
출력 버퍼는 드라이버에서 정보를 받습니다. 읽기 요청의 경우 일반적으로 이 정보는 함수 드라이버가 디바이스에서 수신하는 데이터입니다. 디바이스 I/O 컨트롤 요청의 경우 출력 버퍼는 지정된 요청의 I/O 제어 코드에 상태 또는 기타 정보를 수신할 수 있습니다.
드라이버가 요청의 데이터 버퍼에 액세스하는 데 사용하는 기술은 디바이스의 데이터 버퍼에 액세스하는 드라이버의 방법에 따라 달라질 수 있습니다. UMDF는 다음 버퍼 액세스 방법을 지원합니다.
버전 1.9 이전의 UMDF 버전은 버퍼링된 I/O 액세스 방법만 지원합니다. 이러한 UMDF 버전으로 실행되는 UMDF 기반 드라이버는 모든 읽기, 쓰기 및 디바이스 I/O 제어 요청에 버퍼링된 I/O 메서드만 사용할 수 있습니다. I/O 요청의 데이터 버퍼에 액세스하려면 UMDF 기반 드라이버는 IWDFIoRequest::GetInputMemory 및 IWDFIoRequest::GetOutputMemory 개체 메서드를 사용해야 합니다.
UMDF 버전 1.9부터 버퍼링된 I/O 및 직접 I/O의 두 가지 액세스 메서드를 UMDF 기반 드라이버에서 사용할 수 있습니다. UMDF 버전 1.9 이상용으로 작성된 UMDF 드라이버는 IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer 또는 IWDFIoRequest2::RetrieveOutputMemory 개체 메서드를 사용하여 데이터 버퍼에 액세스해야 합니다.
버퍼링되지 않거나 직접 I/O라고 하는 세 번째 액세스 메서드는 UMDF 기반 드라이버에서 사용할 수 없지만 UMDF는 일부 I/O 요청을 "둘 다" 메서드에서 UMDF 버전이 지원하는 메서드로 변환할 수 있습니다.
대부분의 경우 UMDF 기반 드라이버는 UMDF와 드라이버가 버퍼링된 I/O 또는 직접 I/O를 사용하는지 여부에 관계없이 동일한 UMDF 개체 메서드를 호출하여 데이터 버퍼에 액세스합니다. 직접 I/O는 종종 버퍼 I/O가 제공하는 것보다 더 나은 성능을 제공합니다.
이 항목의 다음 섹션에서는 다음을 설명합니다.
기본 버퍼 액세스 방법 및 기본 버퍼 검색 모드를 지정하는 방법
UMDF가 사용할 버퍼 메서드 및 검색 모드를 선택하는 방법
드라이버가 UMDF에서 사용하는 버퍼 액세스 방법을 가져오는 방법
버퍼링,직접 및 버퍼링되지 않은 직접 버퍼 액세스 메서드를 사용하기 위한 지침
기본 버퍼 액세스 방법 지정
UMDF 버전 1.9 이상은 버퍼링된 I/O 액세스 메서드와 직접 I/O 액세스 방법을 모두 지원합니다. 드라이버는 IWDFDriver::CreateDevice를 호출하기 전에 IWDFDeviceInitialize2::SetIoTypePreference를 호출하여 디바이스의 모든 읽기, 쓰기 및 디바이스 I/O 컨트롤 요청에 사용하려는 액세스 방법을 지정할 수 있습니다. 예를 들어 드라이버가 해당 디바이스 중 하나에 대한 읽기 및 쓰기 요청에 대해 버퍼링된 I/O 메서드에 대해서만 기본 설정을 지정하는 경우 UMDF 드라이버 호스트 프로세스 는 해당 디바이스의 드라이버에 대한 읽기 및 쓰기 요청을 전달할 때 버퍼링된 I/O 메서드를 사용합니다. 드라이버가 직접 I/O에 대한 기본 설정을 지정하는 경우 UMDF는 직접 I/O를 사용할 수 있지만 그렇지 않을 수 있습니다. UMDF가 직접 I/O를 사용하는 경우에 대한 자세한 내용은 UMDF가 I/O 요청에 대한 버퍼 액세스 방법을 선택하는 방법을 참조하세요.
드라이버가 지원하는 각 디바이스에 대해 드라이버는 버퍼링된 I/O, 직접 I/O 또는 디바이스의 버퍼링 또는 직접 I/O에 대한 기본 설정을 지정할 수 있습니다. 드라이버는 읽기 및 쓰기 요청에 한 가지 유형의 액세스 메서드와 디바이스 I/O 제어 요청에 대한 다른 유형의 액세스 방법을 지정할 수 있습니다. 드라이버가 액세스 메서드 기본 설정을 지정하지 않으면 UMDF는 버퍼링된 메서드를 사용합니다.
디바이스 I/O 컨트롤 요청의 경우 I/O 제어 코드(IOCTL)는 버퍼 액세스 방법을 지정합니다. (IOCTL이 액세스 방법을 지정하는 방법에 대한 자세한 내용은 I/O 제어 코드 정의를 참조하세요.) 그러나 UMDF에서 사용하는 액세스 방법이 IOCTL에서 지정하는 액세스 방법과 일치하지 않을 수 있습니다.
버전 1.9 이전의 UMDF 버전에서 UMDF는 항상 모든 I/O 컨트롤 요청에 버퍼링된 액세스 메서드를 사용합니다.
IOCTL이 버퍼링된 I/O를 지정하는 경우 UMDF 버전 1.9 이상에서는 버퍼링된 I/O 액세스 메서드를 사용합니다. IOCTL이 직접 I/O를 지정하고 드라이버가 직접 I/O에 대한 기본 설정을 나타내기 위해 IWDFDeviceInitialize2::SetIoTypePreference 를 호출하는 경우 UMDF는 I/O 요청에 대한 버퍼 액세스 방법을 선택하는 방법에 설명된 대로 직접 I/O를 사용하거나 버퍼링된 I/O를 사용할 수 있습니다. UMDF가 "버퍼링된 I/O 또는 직접 I/O" 메서드를 지정하는 IOCTL을 지원하는 방법에 대한 자세한 내용은 UMDF 드라이버에서 버퍼링된 I/O 또는 직접 I/O 사용을 참조하세요.
버퍼 검색 모드 지정
버전 1.9 이전의 UMDF 버전에서 UMDF는 UMDF가 I/O 요청을 수신하는 즉시 항상 드라이버에서 I/O 요청의 버퍼를 사용할 수 있도록 합니다(버퍼를 UMDF 드라이버 호스트 프로세스에 복사). 이 버퍼 검색 모드를 즉시 검색이라고 합니다. 오류가 발생하면 UMDF는 오류 상태 값으로 I/O 요청을 완료하고 드라이버에 I/O 요청을 전달하지 않습니다.
UMDF 버전 1.9 이상은 즉시 검색 및 지연된 검색 모드를 모두 지원합니다. 지연된 검색 모드는 드라이버가 버퍼에 액세스하려고 시도할 때까지 I/O 요청의 버퍼를 드라이버 호스트 프로세스에 복사하는 것을 연기합니다. 오류가 발생하면 버퍼 액세스 함수는 오류 상태 값을 드라이버에 반환합니다.
드라이버는 각 디바이스에 대해 IWDFDeviceInitialize2::SetIoTypePreference 를 호출할 때 버퍼 검색 모드를 지정할 수 있습니다. 다음 규칙을 사용합니다.
드라이버가 직접 I/O 액세스 방법을 지정하는 경우 지연된 검색 모드도 지정해야 합니다. 직접 I/O는 지연된 검색에서만 작동합니다.
UMDF 버전 1.9 이상에서 실행되도록 작성된 모든 드라이버는 드라이버가 버퍼링된 I/O 액세스 방법을 선택하든지 관계없이 모든 I/O 요청에 대해 지연된 검색 모드를 지정해야 합니다. 지연 검색은 드라이버가 사용하지 않는 버퍼에 액세스하지 않으므로 더 나은 성능을 제공합니다.
드라이버가 버퍼 검색 모드를 지정하지 않으면 UMDF는 즉시 검색을 사용합니다.
드라이버 스택의 모든 UMDF 기반 드라이버는 동일한 검색 모드를 사용해야 합니다. 일부 드라이버가 즉시 검색을 지정하고 일부는 지연된 검색을 지정하는 경우 UMDF는 즉시 검색을 사용합니다.
UMDF가 I/O 요청에 대한 버퍼 액세스 방법을 선택하는 방법
드라이버가 IWDFDeviceInitialize2::SetIoTypePreference를 호출할 때 지정하는 액세스 메서드는 UMDF에서 사용하는 액세스 메서드가 아닐 수 있습니다. UMDF는 다음 규칙을 사용하여 사용할 액세스 방법을 결정합니다.
드라이버 스택의 모든 UMDF 기반 드라이버는 디바이스의 버퍼에 액세스하는 데 동일한 방법을 사용해야 합니다. UMDF에서 일부 드라이버가 디바이스에 버퍼링된 I/O 또는 직접 I/O를 선호하는 반면 다른 드라이버는 디바이스에 버퍼링된 I/O만 선호한다고 판단하는 경우 UMDF는 모든 드라이버에 버퍼링된 I/O를 사용합니다. 하나 이상의 스택 드라이버가 버퍼링된 I/O만 선호하는 반면 다른 드라이버는 직접 I/O만 선호하는 경우 UMDF는 이벤트를 시스템 이벤트 로그에 기록하며 드라이버 스택을 시작하지 않습니다.
드라이버는 IWDFDevice2::GetDeviceStackIoTypePreference 를 호출하여 UMDF가 디바이스의 읽기/쓰기 요청 및 I/O 제어 요청에 할당한 버퍼 액세스 방법을 확인할 수 있습니다.
경우에 따라 드라이버는 IWDFDeviceInitialize2::SetIoTypePreference를 호출할 때 직접 I/O에 대한 기본 설정을 지정하지만 최상의 성능을 위해 UMDF는 하나 이상의 디바이스 요청에 버퍼링된 I/O를 사용합니다. 예를 들어 UMDF는 직접 액세스를 위해 버퍼를 매핑할 수 있는 것보다 더 빠르게 드라이버의 버퍼에 데이터를 복사할 수 있는 경우 작은 버퍼에 버퍼링된 I/O를 사용합니다.
필요에 따라 프레임워크가 직접 I/O를 사용할 가장 작은 버퍼 크기를 결정하는 데 사용하는 REG_DWORD 형식 의 DirectTransferThreshold 레지스트리 값을 설정할 수 있습니다. 일반적으로 프레임워크는 최상의 성능을 제공하는 값을 사용하기 때문에 이 레지스트리 값을 제공할 필요가 없습니다. DirectTransferThreshold 값은 디바이스의 하드웨어 키 아래에 있는 디바이스의 디바이스 매개 변수\WUDF 하위 키 아래에 있습니다.
프레임워크는 다음 규칙을 사용하여 DirectTransferThreshold에서 제공하는 값에 따라 임계값을 결정합니다. 제공된 숫자는 itanium 기반 시스템을 제외하고 유효한 4096의 PAGE_SIZE 가정합니다.
DirectTransferThreshold를 8192보다 작거나 같은 값(또는 2 * PAGE_SIZE)으로 설정하면 프레임워크는 임계값을 8192로 설정합니다. 프레임워크는 8192바이트보다 작은 버퍼에 버퍼링된 I/O를 사용하고 8192바이트보다 크거나 같은 버퍼의 경우 직접 I/O를 사용합니다.
DirectTransferThreshold를 8192보다 큰 값으로 설정하면 프레임워크는 PAGE_SIZE 다음으로 정확한 배수로 반올림됩니다. 다시 말하지만 프레임워크는 임계값보다 작은 버퍼에 버퍼링된 I/O를 사용하고 임계값보다 크거나 같은 버퍼의 경우 직접 I/O를 사용합니다.
UMDF는 메모리 페이지 경계에서 시작되고 끝나는 버퍼 공간에만 직접 I/O를 사용합니다. 버퍼의 시작 또는 끝이 페이지 경계에 있지 않으면 UMDF는 버퍼의 해당 부분에 버퍼링된 I/O를 사용합니다. 즉, UMDF는 여러 I/O 요청으로 구성된 대규모 데이터 전송에 버퍼링된 I/O와 직접 I/O를 모두 사용할 수 있습니다.
디바이스 I/O 제어 요청의 경우 UMDF는 I/O 제어 코드(IOCTL)가 직접 I/O를 지정하고 디바이스의 모든 UMDF 기반 드라이버가 IWDFDeviceInitialize2::SetIoTypePreference 를 호출한 경우에만 직접 I/O를 사용하여 직접 액세스 방법을 지정합니다.
드라이버는 버퍼 액세스 방법에 관계없이 동일한 요청 개체 메서드 집합을 사용하여 데이터 버퍼에 액세스합니다. 따라서 대부분의 드라이버는 일반적으로 UMDF가 I/O 요청에 버퍼링된 I/O 또는 직접 I/O를 사용하는지 여부를 알 필요가 없습니다.
드라이버가 I/O 요청에 대한 액세스 메서드를 가져오는 방법
액세스 방법을 알고 있는 경우 디바이스 및 드라이버의 성능을 향상시킬 수 있는 경우도 있습니다. 이러한 경우 드라이버는 IWDFIoRequest2::GetEffectiveIoType 을 호출하여 I/O 요청의 버퍼 액세스 메서드를 가져올 수 있습니다.
예를 들어 일반적으로 직접 I/O를 사용하는 처리량이 높은 디바이스를 고려해 보세요. 직접 I/O를 사용하므로 드라이버는 애플리케이션이 유효성 검사 후 매개 변수를 수정하지 않도록 매개 변수의 유효성을 검사하기 전에 애플리케이션 지정 매개 변수를 로컬 드라이버 메모리에 복사해야 합니다.
드라이버가 버퍼링된 I/O를 사용하는 버퍼를 받을 수 있고 버퍼링된 I/O 버퍼가 이미 복사되었기 때문에 애플리케이션은 데이터를 수정할 수 없으며 드라이버가 매개 변수의 유효성을 검사하기 전에 매개 변수를 복사할 필요가 없습니다. 따라서 드라이버는 각 요청의 버퍼 액세스 메서드를 검사 매개 변수의 유효성을 검사하기 전에 매개 변수를 복사해야 하는지 여부를 결정해야 합니다.
UMDF 드라이버에서 버퍼링된 I/O 사용
드라이버가 버퍼링된 I/O를 사용하는 경우 UMDF 동작은 요청 유형에 따라 다릅니다. 읽기 및 쓰기 요청의 경우 드라이버 호스트 프로세스는 드라이버가 액세스할 수 있는 단일 중간 버퍼를 만듭니다.
쓰기 요청의 경우 드라이버 호스트 프로세스는 드라이버 스택을 호출하기 전에 호출 애플리케이션의 입력 버퍼에서 입력 정보를 전송합니다. 드라이버는 일반적으로 중간 버퍼에서 입력 정보를 읽고 디바이스에 씁니다.
읽기 요청의 경우 드라이버는 일반적으로 디바이스에서 정보를 읽고 중간 버퍼에 저장합니다. 드라이버 호스트 프로세스는 중간 버퍼의 출력 데이터를 애플리케이션의 출력 버퍼로 복사합니다.
그러나 디바이스 I/O 제어 요청의 경우 드라이버 호스트 프로세스는 드라이버가 액세스할 수 있는 두 개의 별도 버퍼를 만듭니다. 이는 버퍼링된 I/O를 사용하여 전송된 읽기, 쓰기 및 디바이스 I/O 제어 요청으로 인해 드라이버가 단일 중간 버퍼에 액세스하는 WDM 및 KMDF 드라이버의 동작과 다릅니다. 이 경우 출력 버퍼는 처음에는 아무 것도 포함하지 않으며 드라이버는 이 버퍼에서 읽지 않아야 합니다. 또한 드라이버가 입력 버퍼에 쓰는 모든 데이터는 삭제되고 호출 애플리케이션에 반환되지 않습니다.
버퍼링된 I/O를 선택하는 시기에 대한 지침은 WDF_DEVICE_IO_TYPE.
UMDF 버전 1.9 이상은 요청 버퍼의 즉시 또는 지연된 검색을 지원할 수 있습니다. 자세한 내용은 WDF_DEVICE_IO_BUFFER_RETRIEVAL 참조하세요.
즉시 버퍼 검색 모드를 사용하는 드라이버는 IWDFIoRequest::GetInputMemory 및 IWDFIoRequest::GetOutputMemory 를 사용하여 버퍼에 액세스해야 합니다.
지연된 버퍼 검색 모드를 사용하는 드라이버는 IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer 또는 IWDFIoRequest2::RetrieveOutputMemory를 호출하여 버퍼에 액세스할 수 있습니다.
UMDF 드라이버에서 직접 I/O 사용
드라이버가 직접 I/O를 사용하는 경우 드라이버 호스트 프로세스는 I/O 요청의 발신자(일반적으로 사용자 모드 애플리케이션)가 지정한 버퍼 공간의 접근성을 확인하고 버퍼 공간을 실제 메모리로 잠급니다. 그런 다음 드라이버에 버퍼 공간에 직접 액세스할 수 있도록 합니다.
직접 I/O를 선택하는 시기에 대한 지침은 WDF_DEVICE_IO_TYPE.
드라이버는 IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer 또는 IWDFIoRequest2::RetrieveOutputMemory를 호출하여 버퍼에 액세스할 수 있습니다.
UMDF 드라이버에서 버퍼링된 I/O 또는 직접 I/O 사용
버퍼링된 I/O 또는 직접 I/O 메서드(또는 "둘 다" 메서드)로 알려진 버퍼 액세스 메서드를 사용하면 드라이버가 애플리케이션의 요청 버퍼 포인터에 직접 액세스할 수 있습니다. UMDF 기반 드라이버는 이 액세스 방법을 사용할 수 없습니다.
그러나 일부 IOCTL(디바이스 I/O 제어 코드)의 정의 는 요청이 "둘 다" 메서드를 사용하도록 지정합니다. 필요에 따라 UMDF는 이러한 디바이스 I/O 제어 요청의 버퍼 액세스 방법을 버퍼링된 I/O 또는 직접 I/O로 변환할 수 있습니다. 다음 단계를 사용합니다.
드라이버의 INF 파일의 INF DDInstall 섹션에 UmdfMethodNeitherAction 지시문을 포함합니다. 지시문 값을 설정하여 UMDF가 "둘 다" 액세스 메서드를 사용하는 디바이스 I/O 제어 요청을 드라이버에 전달해야 함을 나타낼 수 있습니다. 그렇지 않으면 UMDF는 오류 상태 값으로 이러한 I/O 요청을 완료합니다.
UMDF가 버퍼링된 I/O 또는 직접 I/O 에 제공하는 개체 메서드를 사용하여 I/O 요청의 버퍼에 액세스합니다.
UMDF가 액세스 메서드를 버퍼링된 I/O 또는 직접 I/O로 변환할 수 있다고 확신하는 경우에만 "둘 다" 메서드를 사용하는 IOCTL 요청을 지원해야 합니다. 예를 들어 IOCTL이 I/O 제어 코드에 대한 버퍼 설명에 설명된 버퍼 사양 규칙을 따르지 않는 사용자 지정된 요청을 지정하는 경우 UMDF는 버퍼를 변환할 수 없습니다.