MmLockPagableCodeSection 매크로(wdm.h)
MmLockPagableCodeSection 루틴은 특수 컴파일러 지시문으로 표시된 드라이버 루틴 집합을 포함하는 드라이버 코드의 섹션을 시스템 공간으로 잠급니다.
구문
void MmLockPagableCodeSection(
[in] Address
);
매개 변수
[in] Address
기호 주소를 지정합니다. 이 주소는 일반적으로 #pragma alloc_text(PAGExxxx, driverfunction)와 같이 표시된 드라이버 코드 섹션 내의 드라이버 함수 이름입니다. PAGExxxx 섹션의 모든 함수는 이 함수가 반환될 때 잠기도록 보장됩니다.
반환 값
없음
설명
MmLockPagableCodeSection 은 운영 체제에서 드라이버 코드의 이 섹션을 식별하는 데 사용하는 불투명 값을 반환합니다. 이 불투명 값은 이후에 MmLockPagableSectionByHandle (드라이버가 잠금을 해제한 다음 나중에 섹션을 다시 잠글 경우) 또는 MmUnlockPagableImageSection에 전달할 수 있습니다.
MmLockPagableCodeSection 루틴 및 MmUnlockPagableImageSection(반대 작업을 수행하는 루틴)은 다음을 수행할 수 있는 드라이버를 지원합니다.
드라이버 디바이스에 대한 들어오는 I/O 요청으로 이러한 루틴이 IRP를 처리해야 할 때까지 드라이버 루틴의 하위 집합을 상주 메모리에 로드하는 것을 연기합니다.
I/O 요청 처리를 완료하고 드라이버 디바이스에 대한 추가 요청이 현재 예상되지 않을 때 동일한 드라이버 루틴 하위 집합을 페이징 아웃에 사용할 수 있도록 합니다.
MmLockPagableCodeSection, MmLockPagableSectionByHandle 및 MmUnlockPagableImageSection 은 다음과 같은 특성을 가진 디바이스 및 중간 드라이버에서 사용하기 위한 것입니다.
드라이버에는 시스템이 실행되는 동안 필요하지 않을 수 있는 코드 경로가 있지만 필요한 경우 임의의 스레드 컨텍스트 또는 IRQL >= DISPATCH_LEVEL 실행되기 때문에 드라이버의 코드가 상주해야 합니다.
드라이버는 페이징 가능한 루틴을 로드해야 하는 시기와 다시 페이징할 수 있는 시기를 정확하게 결정할 수 있습니다.
예를 들어 시스템에서 제공하는 내결함성 디스크 드라이버는 미러 집합, 스트라이프 집합 및 볼륨 집합 만들기를 지원합니다. 그러나 특정 머신은 미러 집합으로만 구성할 수 있으며, 스트라이프 집합, 볼륨 집합만 또는 이러한 세 가지 가능한 옵션의 조합으로만 구성할 수 있습니다. 이러한 상황에서 시스템 ftdisk 드라이버는 명시적으로 미러, 스트라이프 및 볼륨 집합을 페이저블 코드 섹션에 속하는 것으로 표시하는 루틴을 표시하여 로드된 이미지의 크기를 줄입니다. 드라이버 초기화 중에 사용자가 미러, 스트라이프 또는 볼륨 집합을 사용하도록 디스크를 구성한 경우에만 페이저블 코드 섹션이 상주하게 됩니다. 사용자가 디스크를 동적으로 다시 분할하는 경우 ftdisk 드라이버는 사용자가 요청하는 미러, 스트라이프 또는 볼륨 집합을 지원하는 데 필요한 추가 페이지 가능 코드 섹션을 잠글 수 있습니다.
다른 예로 시스템에서 제공하는 직렬 및 병렬 드라이버에는 배타적 I/O용으로 특정 포트를 열 때와 열린 포트에 대한 핸들이 각각 해제될 때 호출되는 DispatchCreate 및 DispatchClose 루틴이 있습니다. 그러나 직렬 및 병렬 I/O 요청은 최종 사용자가 현재 실행 중인 애플리케이션과 최종 사용자가 현재 실행 중인 애플리케이션 옵션에 따라 산발적으로 결정됩니다. 이러한 상황에서 시스템 직렬 및 병렬 드라이버는 많은 루틴을 DispatchCreate 루틴이 I/O에 대해 첫 번째 포트가 열릴 때만 상주하게 만드는 페이딩 가능한 코드 섹션에 속하는 것으로 표시하여 로드된 이미지의 크기를 줄입니다.
앞의 각 시스템 드라이버는 페이징 가능한 섹션에 대한 두 가지 조건을 모두 충족합니다. 드라이버에는 시스템이 실행되는 동안 필요하지 않을 수 있는 코드 경로가 있으며, 드라이버는 페이징 가능한 섹션을 로드해야 하는 시기를 정확하게 확인할 수 있으며 다시 페이징할 수 있습니다.
섹션을 잠그는 작업은 비용이 많이 들기 때문에 드라이버가 둘 이상의 위치에서 페이징 가능한 코드 섹션을 잠그는 경우 첫 번째 요청에 MmLockPagableCodeSection 을 사용합니다. MmLockPagableCodeSection에서 반환된 핸들을 전달하는 MmLockPagableSectionByHandle을 호출하여 후속 잠금 요청을 만듭니다. 메모리 관리자는 불투명 반환 값을 사용하여 로드된 모듈 목록을 검색하는 대신 관련 섹션을 빠르게 찾기 때문에 핸들을 통해 잠금을 사용하면 드라이버 성능이 크게 향상됩니다. 잠김 섹션은 MmUnlockPagableImageSection을 호출하여 잠금 해제됩니다.
페이저블 코드 섹션 내의 각 드라이버 루틴은 다음 컴파일러 지시문으로 표시되어야 합니다.
#pragma alloc_text(PAGExxxx, DriverRoutine)
여기서 xxxx 는 호출자의 페이저블 섹션에 대한 선택적 4자 고유 식별자이며 DriverRoutine 은 페이저블 코드 섹션에 포함할 진입점입니다. 키워드(keyword) PAGE 및 최대 4자까지 사용할 수 있는 드라이버 결정 접미사는 대/소문자를 구분합니다. 즉, PAGE를 대문자로 표시해야 합니다.
예를 들어 드라이버의 DispatchCreate 루틴에서 MmLockPagableCodeSection을 한 번 호출하면 동일한 PAGExxxx 식별자로 표시된 모든 드라이버 루틴을 포함하는 전체 섹션이 시스템 공간에 잠깁니다.
특정 유형의 드라이버 루틴은 다음을 포함하여 드라이버의 페이지 가능 섹션에 포함할 수 없습니다.
ISR을 페이저블로 만들지 마세요. 특히 인터럽트 벡터를 공유할 수 있는 경우 디바이스를 사용하지 않더라도 디바이스 드라이버가 가짜 인터럽트를 받을 수 있습니다. 일반적으로 드라이버가 디바이스에서 인터럽트를 명시적으로 사용하지 않도록 설정할 수 있더라도 ISR을 페이저블로 설정하면 안 됩니다.
드라이버가 DPC가 큐에 대기되는 시기를 제어할 수 없는 경우(예: ISR에서 큐에 대기할 수 있는 DpcForIsr 또는 CustomDpc 루틴) DPC 루틴을 페이징 가능으로 만들지 마세요. 일반적으로 IRQL >= DISPATCH_LEVEL 실행되고 임의 스레드 컨텍스트에서 또는 임의 외부 이벤트에 대한 응답으로 호출할 수 있는 드라이버 루틴은 페이딩할 수 없습니다.
시스템 페이징 I/O 경로의 일부일 수 있는 드라이버에서는 DispatchRead 또는 DispatchWrite 루틴을 페이징할 수 없습니다. 시스템 페이지 파일을 포함할 수 있는 디스크의 드라이버에는 시스템이 실행되는 동안 상주하는 DispatchRead 및 DispatchWrite 루틴이 있어야 합니다. 모든 드라이버가 이러한 디스크 드라이버 위에 계층화되어야 합니다.
컴파일러 지시문 #pragma alloc_text(PAGExxxx, ...) 로 표시된 페이징 가능 섹션의 루틴은 컴파일러 지시문 #pragma alloc_text(INIT, ...)로 표시된 루틴과 다릅니다. INIT 섹션의 루틴은 페이지할 수 없으며 드라이버가 DriverEntry 또는 루틴 다시 초기화 (있는 경우)에서 반환되는 즉시 삭제됩니다.
메모리 관리자는 드라이버의 페이지 가능 섹션에서 내부 잠금 수를 유지 관리합니다. MmLockPagableCodeSection에 대한 호출은 이 수를 증가시키고 상호 MmUnlockPagableImageSection은 수를 감소합니다. 이 수가 0이 아니면 드라이버의 페이징 가능 섹션을 페이징할 수 없습니다.
페이지 가능한 코드 섹션을 만드는 방법에 대한 자세한 내용은 드라이버 페이지 가능 만들기를 참조하세요.
요구 사항
요구 사항 | 값 |
---|---|
대상 플랫폼 | 데스크톱 |
헤더 | wdm.h(Wdm.h, Ntddk.h, Ntifs.h 포함) |
라이브러리 | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | <=APC_LEVEL |