다음을 통해 공유


PIO에서 직접 I/O 사용

DMA가 아닌 프로그래밍된 I/O(I/O)를 사용하는 드라이버는 사용자 공간 버퍼를 시스템 공간 주소 범위에 두 배로 매핑해야 합니다. 다음 그림에서는 I/O 관리자가 직접 I/O를 사용하는 PIO 전송 작업에 대한 IRP_MJ_READ 요청을 설정하는 방법을 보여 줍니다.

pio를 사용하는 디바이스에 대한 직접 i/O를 보여 주는 다이어그램

그림에서는 PIO를 사용하는 디바이스가 동일한 작업을 처리하는 방법을 보여 줍니다.

  1. 사용자 공간 가상 주소의 일부 범위는 현재 스레드의 버퍼를 나타내며, 해당 버퍼의 콘텐츠는 실제로 물리적으로 불협화음이 있는 일부 페이지에 저장될 수 있습니다. 버퍼 길이가 0이 아닌 경우 I/O 관리자는 이 버퍼를 설명하는 MDL을 만듭니다.

  2. I/O 관리자는 스레드가 버퍼를 나타내는 다양한 사용자 공간 가상 주소를 전달하는 현재 스레드의 읽기 요청을 처리합니다.

  3. I/O 관리자 또는 FSD는 사용자가 제공한 버퍼에서 접근성을 확인합니다. I/O 관리자가 MDL을 만든 경우 사용자 버퍼에 대한 가상 주소 범위를 지정하는 MDL을 사용하여 MmProbeAndLockPages 를 호출합니다. MmProbeAndLockPages는 MDL의 해당 실제 주소 범위도 채웁니다.

  4. I/O 관리자는 전송 작업을 요청하는 IRP의 MDL(MdlAddress)에 대한 포인터를 제공합니다. 드라이버가 IRP를 완료한 후 I/O 관리자 또는 파일 시스템에서 MmUnlockPages 를 호출할 때까지 MDL에 설명된 실제 페이지는 잠겨 있고 버퍼에 할당된 상태로 유지됩니다. 그러나 IRP가 디바이스 드라이버 또는 디바이스 드라이버 위에 계층화될 수 있는 중간 드라이버로 전송되기 전에도 이러한 MDL의 가상 주소는 보이지 않으며 유효하지 않을 수 있습니다.

  5. 드라이버에 시스템(가상) 주소가 필요한 경우 드라이버는 IRP의 MdlAddress 포인터를 사용하여 MmGetSystemAddressForMdlSafe를 호출하여 MDL의 사용자 공간 가상 주소를 시스템 공간 주소 범위에 두 배로 매핑합니다. 위의 그림에서 AliasBuff는 이중 매핑된 주소를 설명하는 MDL을 나타냅니다.

  6. 드라이버는 이중 매핑된 MDL(AliasBuff)의 시스템 공간 가상 주소 범위를 사용하여 데이터를 메모리로 읽습니다.

드라이버가 IoCompleteRequest를 호출하여 IRP를 완료하면 드라이버가 MmGetSystemAddressForMdlSafe라고 하는 경우 I/O 관리자 또는 파일 시스템은 MDL의 이중 매핑된 시스템 공간 범위를 해제합니다. I/O 관리자 또는 파일 시스템은 MDL에 설명된 페이지의 잠금을 해제하고 드라이버를 대신하여 MDL 및 IRP를 삭제합니다. 성능을 향상시키려면 드라이버는 가상 주소를 사용해야 하는 경우가 아니면 3단계에서 설명한 대로 MDL 물리적 주소를 시스템 공간에 두 배로 매핑하지 않아야 합니다. 이렇게 하면 시스템 페이지 테이블 항목이 불필요하게 사용되며 드라이버 성능과 확장성을 모두 줄일 수 있습니다. 또한 대부분의 이전 드라이버는 이 상황을 처리할 수 없으므로 페이지 테이블 항목이 부족하면 시스템이 충돌할 수 있습니다.

현재 사용자 스레드의 버퍼와 스레드 자체는 해당 스레드가 현재인 동안에만 실제 메모리에 상주하도록 보장됩니다. 이전 그림에 표시된 스레드의 경우 다른 프로세스의 스레드가 실행되는 동안 사용자 버퍼의 콘텐츠를 보조 스토리지로 페이징할 수 있습니다. 다른 프로세스의 스레드가 실행되면 메모리 관리자가 원래 스레드의 버퍼를 포함하는 해당 물리적 페이지를 잠그고 유지하지 않는 한 요청 스레드 버퍼에 대한 시스템 실제 메모리를 덮어쓸 수 있습니다.

그러나 메모리 관리자가 버퍼의 실제 페이지를 유지하더라도 버퍼에 대한 원래 스레드의 가상 주소는 다른 스레드가 최신 상태인 동안에는 표시되지 않습니다. 따라서 드라이버는 MmGetMdlVirtualAddress 에서 반환된 가상 주소를 사용하여 메모리에 액세스할 수 없습니다. 패킷 기반 시스템 또는 버스 master DMA를 사용하여 데이터를 전송하려면 이 루틴의 호출자가 IRP의 MdlAddress 포인터와 함께 MapTransfer에 결과를 전달해야 합니다.