Программирование драйверов Windows


Операции с памятью - часть 4


Вызов IoAllocateMdl создает структуру MDL списка для указанного виртуального адреса (пользовательского или системного адресного пространства) с указанной длиной.

Вызов MmProbeAndLockPages проверяет присутствие страниц в физической памяти, подгружает (для страничной памяти), если они отсутствуют, и производит их фиксацию (после чего данные страницы не могут быть сброшены в страничный файл на жестком диске). Для корректного вызова MmProbeAndLockPages

по поводу MDL, составленного для страничной памяти, программный поток должен работать на уровне IRQL ниже DISPATCH_LEVEL &#8212 чтобы позволить отработать системному коду, если страница окажется в страничном файле. (В случае, если исходный буфер находился бы в нестраничной памяти, то данный вызов можно было бы сделать с уровня IRQL равном DISPATCH_LEVEL или ниже.)

Функция MmGetSystemAddressForMdl возвращает виртуальный адрес, вычисленный из MDL списка, так, будто рассматриваемая область памяти находится в системном адресном пространстве, а именно &#8212 в нестраничном пуле. Этот адрес можно использовать в любом месте кода драйвера на любых уровнях IRQL, даже в процедуре обработки прерываний. Контекст выполнения для этого адреса не имеет никакого значения. (Справедливости ради, следует отметить, что перевод в системный адрес не является обязательной операцией, можно и далее использовать MDL список, что позволяют делать, в частности, вызовы нижних драйверов в стеке.) Вызов (точнее, макроопределение) MmGetSystemAddгessForMdl являeтcя устаревшим, и его следует использовать только в WDM драйверах, предназначенных для работы еще и в Windows 98. Использование макроопределения MmGetSystemAddressForMdlSafe

является предпочтительным. Оба эти макроопределения могут быть вызваны из кода, работающего на уровне IRQL не выше DISPATH_LEVEL.

Вызов MmUnlockPages отменяет фиксацию страниц в оперативной памяти, а вызов IoFreeMdl уничтожает структуру MDL списка.

Чтобы отследить ошибки, связанные с фиксацией блока виртуальной памяти в памяти оперативной, рекомендуется выполнять вызов MmProbeAndLockPages

внутри try-except блока, например:

__try { MmProbeAndLockPages( pMdl, UserMode, IoModifyAccess); } __except( EXCEPTION_EXECUTE_HANDLER) { pIrp-&#62IoStatus.Status = STATUS_ACCESS_VIOLATION; pIrp-&#62IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_CONFLICTING_ADDRESSES; }

На рассмотренном выше примере видно, что операционная система предоставляет достаточно инструментов для преобразования адресов пользовательского пространства в адреса системного пространства и физические адреса. Важно только корректно отслеживать, когда и что следует использовать.

Ниже приводятся более полные сведения о системных функциях, которые полезны для работы с виртуальной и физической памятью.




Начало  Назад  Вперед