다음을 통해 공유


연결된 MDL 구조를 보내는 방법

이 문서에서는 USB 드라이버 스택의 연결된 MDL 기능과 클라이언트 드라이버가 MDL 구조 체인으로 전송 버퍼를 보낼 수 있는 방법을 설명합니다.

대부분의 USB 호스트 컨트롤러에는 전송 버퍼가 거의 연속되어야 합니다. 사실상 연속적이라는 것은 버퍼가 페이지의 아무 곳에서나 시작되고 끝날 수 있지만 나머지 버퍼는 페이지 경계에서 시작되고 끝나야 한다는 것을 의미합니다. 많은 USB 클라이언트 드라이버가 해당 요구 사항을 충족할 수 있습니다. 그러나 특정 클라이언트 드라이버, 특히 버퍼에 추가 데이터를 추가하거나 제거해야 하는 드라이버의 경우 전송 버퍼에 대해 거의 연속된 메모리를 할당하는 것이 바람직하지 않습니다.

예를 들어 세 개의 드라이버, 네트워크 프로토콜 드라이버, 중간 드라이버 및 미니포트 드라이버의 네트워킹 스택을 고려합니다. 프로토콜 드라이버는 전송을 시작하고 스택의 다음 드라이버인 중간 드라이버로 패킷을 보냅니다. 중간 드라이버는 패킷에 사용자 지정 헤더(별도의 메모리 블록에 포함됨)를 추가하려고 합니다. 중간 드라이버는 해당 헤더와 수신된 패킷을 스택의 다음 드라이버인 미니포트 드라이버로 보냅니다. 미니포트 드라이버는 USB 드라이버 스택과 인터페이스되므로 사실상 연속 전송 버퍼를 준비해야 합니다. 이러한 버퍼를 만들기 위해 미니포트 드라이버는 큰 버퍼를 할당하고 사용자 지정 헤더를 추가한 다음 페이로드를 복사합니다. 페이로드는 일반적으로 크므로 전체 페이로드를 복사하면 성능에 큰 영향을 미칠 수 있습니다.

클라이언트 드라이버는 전송 버퍼를 MDL(메모리 설명자 목록) 체인 으로 전송하여 성능 영향을 극복할 수 있습니다. Windows 8 새 USB 드라이버 스택은 클라이언트 드라이버에서 연결된 MDL(MDL 참조)을 수락할 수 있습니다. 연결된 MDL을 제공하면 클라이언트 드라이버는 불필요한 복사 작업을 수행하는 대신 메모리에서 불연연한 페이지를 참조할 수 있습니다. 이 기능은 버퍼의 수, 크기 및 맞춤에 대한 제한을 제거하여 전송 버퍼를 실제 메모리로 분할할 수 있도록 합니다.

연결된 MDL을 사용하려면 클라이언트 드라이버가 Windows에서 로드한 기본 USB 드라이버 스택이 기능을 지원하는지 여부를 감지한 다음 적절한 순서로 MDL 체인을 빌드해야 합니다.

시작하기 전에

연결된 MDL 기능은 대량, 등시 및 인터럽트 전송에 대해서만 지원됩니다. 연결된 MDL 기능을 쿼리하기 전에 클라이언트 드라이버에 USB 드라이버 스택을 사용하여 드라이버 등록을 위한 USBD 핸들이 있는지 확인합니다. USBD 핸들을 만들려면 USBD_CreateHandle 호출합니다. 일반적으로 클라이언트 드라이버는 AddDevice 루틴에서 USBD 핸들을 만듭니다.

클라이언트 드라이버의 IRP_MN_START_DEVICE 처리기에서 또는 나중에 언제든지 연결된 MDL 기능을 쿼리할 수 있습니다. 클라이언트 드라이버는 AddDevice 루틴에서 이 기능을 쿼리해서는 안됩니다.

지침

  1. USBD_QueryUsbCapability 루틴을 호출하여 USB 드라이버 스택이 연결된 MDL 기능을 지원하는지 여부를 확인합니다. 해당 기능을 쿼리하려면 USBCapabilityChainedMdls를 GUID로 지정합니다. OutputBuffer 매개 변수를 NULL로 설정하고 OutputBufferSize 매개 변수를 0으로 설정합니다.

  2. USBD_QueryUsbCapability 반환된 NTSTATUS 값을 확인하고 결과를 평가합니다. 루틴이 성공적으로 완료되면 연결된 MDL 기능이 지원됩니다. 다른 값은 기능이 지원되지 않음을 나타냅니다.

  3. MDL 체인을 만듭니다. 각 MDL에는 다른 MDL을 가리키는 Next 포인터가 있습니다.

    드라이버는 다음 포인터를 수동으로 설정하여 체인 MDL을 빌드할 수 있습니다.

    앞의 예제에서 프로토콜 드라이버는 패킷을 MDL로 보냅니다. 중간 드라이버는 헤더 데이터를 사용하여 메모리 블록을 참조하는 다른 MDL 을 만들 수 있습니다. 체인을 만들기 위해 중간 드라이버는 헤더 MDL의 Next 포인터를 프로토콜 드라이버에서 받은 MDL을 가리킬 수 있습니다. 그런 다음 중간 드라이버는 두 개의 MDL 체인을 미니포트 드라이버로 전달할 수 있습니다. 이 드라이버는 요청에 대한 URB의 연결된 MDL에 대한 참조를 제공하고 USB 드라이버 스택에 요청을 제출합니다. 자세한 내용은 MDL 사용을 참조하세요.

  4. 연결된 MDL을 사용하는 I/O 요청에 대한 URB를 빌드하는 동안 연결된 URB 구조의 TransferBufferMDL 멤버(예: _URB_BULK_OR_INTERRUPT_TRANSFER 또는 _URB_ISOCH_TRANSFER)를 체인의 첫 번째 MDL로 설정하고 TransferBufferLength를 전송할 총 바이트 수로 설정합니다. 데이터는 MDL 체인에서 둘 이상의 MDL 항목에 걸쳐 있을 수 있습니다.

    Windows 8 클라이언트 드라이버가 데이터 전송에 연결된 MDL을 사용할 수 있도록 하는 두 가지 새로운 유형의 URB 함수가 추가되었습니다. 이 기능을 사용하려면 URB 헤더의 Function 멤버를 다음 URB 함수 중 하나로 설정해야 합니다.

    • URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_USING_CHAINED_MDL
    • URB_FUNCTION_ISOCH_TRANSFER_USING_CHAINED_MDL

    이러한 URB 함수에 대한 자세한 내용은 _URB_HEADER 참조하세요.

설명

드라이버 스택이 연결된 MDL을 수락할 수 있는지 여부를 확인하기 위해 기본 USB 드라이버 스택을 쿼리하는 코드 예제는 USBD_QueryUsbCapability 참조하세요.