티스토리 뷰
연속적인 가상 메모리 주소 범위에 걸쳐있는 I / O 버퍼는 여러 물리적 페이지에 분산 될 수 있으며 이러한 페이지는 불연속적일 수 있습니다. 운영 체제는 MDL ( Memory Descriptor List )을 사용하여 가상 메모리 버퍼의 실제 페이지 레이아웃을 설명합니다.
MDL은 I / O 버퍼가 상주하는 물리적 메모리를 설명하는 데이터 배열이 뒤 따르는 MDL 구조 로 구성됩니다 . MDL의 크기는 MDL이 설명하는 I / O 버퍼의 특성에 따라 다릅니다. MDL의 필요한 크기를 계산하고 MDL을 할당하고 해제하기 위해 시스템 루틴을 사용할 수 있습니다.
MDL 구조는 반투명입니다. 드라이버는 이 구조 의 Next 및 MdlFlags 멤버 에만 직접 액세스해야합니다 . 이 두 멤버를 사용하는 코드 예제는 다음 예제 섹션을 참조하십시오.
MDL의 나머지 멤버는 불투명합니다. MDL의 불투명 멤버에 직접 액세스하지 마십시오. 대신 운영 체제가 구조에 대한 기본 작업을 수행하기 위해 제공하는 다음 매크로를 사용하십시오.
MmGetMdlVirtualAddress 는 MDL에 의해 설명 된 I / O 버퍼의 가상 메모리 주소를 반환합니다.
MmGetMdlByteCount 는 I / O 버퍼의 크기를 바이트 단위로 반환합니다.
MmGetMdlByteOffset 은 I / O 버퍼 시작의 실제 페이지 내에서 오프셋을 반환합니다.
IoAllocateMdl 루틴을 사용하여 MDL을 할당 할 수 있습니다 . MDL을 해제하려면 IoFreeMdl 루틴을 사용하십시오 . 또는 비 페이징 메모리 블록을 할당 한 다음 MmInitializeMdl 루틴 을 호출 하여이 메모리 블록을 MDL로 포맷 할 수 있습니다 .
IoAllocateMdl 이나 MmInitializeMdl 모두 MDL 구조를 따르는 데이터 배열을 초기화 하지 않습니다 . 비 페이징 메모리의 드라이버 할당 블록에 상주하는 MDL의 경우 MmBuildMdlForNonPagedPool 을 사용 하여 I / O 버퍼가 상주하는 실제 메모리를 설명하기 위해이 배열을 초기화하십시오.
페이징 가능한 메모리의 경우 가상 메모리와 실제 메모리 간의 통신은 일시적이므로 MDL 구조를 따르는 데이터 배열은 특정 상황에서만 유효합니다. MmProbeAndLockPages 를 호출 하여 페이징 가능한 메모리를 제자리에 고정하고 현재 레이아웃에 대해이 데이터 배열을 초기화합니다. 호출자가 MmUnlockPages 루틴을 사용할 때까지 메모리가 페이징되지 않으며이 시점에서 데이터 배열의 내용이 더 이상 유효하지 않습니다.
MmGetSystemAddressForMdlSafe의 루틴은 이미 시스템 주소 공간에 매핑되지 않은 경우, 시스템 주소 공간에서 가상 주소로 지정된 MDL에 의해 설명되어있는 물리적 페이지를 매핑합니다. 원래 가상 주소는 원래 컨텍스트에서만 사용할 수 있고 언제든지 삭제할 수있는 사용자 주소 일 수 있으므로이 가상 주소는 I / O를 수행하기 위해 페이지를 살펴 봐야하는 드라이버에 유용합니다.
IoBuildPartialMdl 루틴 을 사용하여 부분 MDL을 빌드하는 경우 호출자는 전달할 가상 주소를 결정할 때 MmGetSystemAddressForMdlSafe 루틴 대신 MmGetMdlVirtualAddress 를 사용해야합니다 . IoBuildPartialMdl 은 소스 MDL에서 MmGetMdlVirtualAddress가 리턴 하는 주소를 사용 하여 대상 MDL. 주소가 다른 경우 (예 : 첫 번째 주소가 사용자 주소 인 경우) MmGetSystemAddressForMdlSafe가 반환 하는 주소를 전달 하면 데이터가 손상되거나 버그 검사가 발생할 수 있습니다.
드라이버가 호출하면 IoAllocateMdl를 , 그것은으로 IRP에 대한 포인터를 지정하여 새로 할당 MDL과 IRP를 연결할 수 있습니다 IRP의 의 매개 변수 IoAllocateMdl . IRP에는 하나 이상의 MDL이 연결될 수 있습니다. IRP에 연결된 단일 MDL이있는 경우 IRP의 MdlAddress 멤버는 해당 MDL을 가리 킵니다. IRP에 연관된 MDL 이 여러 개있는 경우 MdlAddress 는 IRP와 연관된 MDL의 링크 된 목록 ( MDL 체인 이라고 함)에서 첫 번째 MDL을 가리 킵니다 . MDL은 다음 구성원에 의해 연결됩니다 . 체인에서 마지막 MDL 의 다음 멤버는 NULL 로 설정 됩니다 .
드라이버가 IoAllocateMdl을 호출 할 때 SecondaryBuffer 매개 변수에 FALSE 를 지정 하면 IRP의 MdlAddress 멤버가 새 MDL을 가리 키도록 설정됩니다. 경우 SecondaryBuffer가 있다 TRUE , 루틴을 삽입 MDL 체인의 끝에 새로운 MDL.
IRP가 완료되면 시스템은 IRP와 연관된 모든 MDL을 잠금 해제하고 해제합니다. 시스템은 I / O 완료 루틴을 대기시키기 전에 MDL을 잠금 해제하고 I / O 완료 루틴이 실행 된 후 해제합니다.
드라이버는 각 MDL 의 다음 멤버를 사용하여 체인의 다음 MDL에 액세스 하여 MDL 체인을 통과 할 수 있습니다 . 드라이버는 다음 멤버 를 업데이트하여 MDL을 수동으로 체인에 삽입 할 수 있습니다 .
MDL 체인은 일반적으로 단일 I / O 요청과 관련된 버퍼 배열을 관리하는 데 사용됩니다. 예를 들어 네트워크 드라이버는 네트워크 작업에서 각 IP 패킷에 대해 하나의 버퍼를 사용할 수 있습니다. 배열의 각 버퍼에는 체인에 자체 MDL이 있습니다. 드라이버가 요청을 완료하면 버퍼를 하나의 큰 버퍼로 결합합니다. 그런 다음 시스템은 요청에 할당 된 모든 MDL을 자동으로 정리합니다.
I / O 관리자는 I / O 요청을 자주 소스입니다. I / O 관리자가 I / O 요청을 완료하면 I / O 관리자는 IRP를 해제하고 IRP에 연결된 MDL을 해제합니다. 이러한 MDL 중 일부는 장치 스택의 I / O 관리자 아래에있는 드라이버에 의해 IRP에 연결되었을 수 있습니다. 마찬가지로 드라이버가 I / O 요청의 소스 인 경우 드라이버는 I / O 요청이 완료 될 때 IRP 및 IRP에 연결된 MDL을 정리해야합니다.
VOID MyFreeMdl(PMDL Mdl)
{
PMDL currentMdl, nextMdl;
for (currentMdl = Mdl; currentMdl != NULL; currentMdl = nextMdl)
{
nextMdl = currentMdl->Next;
if (currentMdl->MdlFlags & MDL_PAGES_LOCKED)
{
MmUnlockPages(currentMdl);
}
IoFreeMdl(currentMdl);
}
} '프로그래밍' 카테고리의 다른 글
| Windows 필터링 플랫폼 트래픽 검사 샘플 (0) | 2020.03.02 |
|---|---|
| Windows 메모리 공간 개요 (0) | 2020.01.10 |
| Windows 필터링 플랫폼(WFP) 로드맵 (0) | 2019.12.18 |
| Windows 필터링 플랫폼(WFP)의 새로운 기능 (0) | 2019.12.18 |
| Windows 필터링 플랫폼 콜아웃 드라이버 소개 (0) | 2019.12.16 |
- Total
- Today
- Yesterday
- 부동산분석
- Python
- ChatGPT
- 개발자
- go
- openai
- 내집마련
- 재테크
- 생각
- SWiFT
- 프로그래밍
- 주식투자
- Backend
- reactjs
- golang
- Java
- MacOS
- 오리역
- 카톡업데이트
- AI
- Spring
- Linux
- react
- ios
- CSS
- HTML
- Frontend
- JavaScript
- 카카오톡
- 부동산
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |