Люди добрые, сами мы не местные, помогите кто чем сможет... Вводная часть: имеются страницы физической памяти (то есть locked, fixed, etc), заполненные некоторой сигнатурой. Задача: из драйвера найти все эти страницы (количество заранее известно) и построить из них буфер для дальнейшего использования драйвером. Теперь вопросы: 1) как из драйвера узнать общий объем физической памяти на данном компьютере? Вопрос не самый важный, но желательный. Можно конечно перебирать все страницы памяти начиная с нулевой и пока не будут найдены все нужные страницы. Но на всякий случай хотелось бы иметь верхний предел поиска. 2) Как построить буфер из произвольного списка страниц? Чего-то я не пойму, как создать пустой MDL, то есть не связанный с какой-либо памятью. 3) как привязать MDL к виртуальному адресу? Заранее прошу прощения, если вопросы глупые. Опыт написания драйверов у меня есть, но вот только не под Windows. Чтение MSDN просветления не вызвало на всякий случай: Дело происходит под XP.
<font color="gray][ LightElf</font><!--color--><font color="gray]: как из драйвера узнать общий объем физической памяти на данном компьютере? ]</font><!--color--> Код (Text): ZwQuerySystemInformation, SystemBasicInformation,... typedef struct _SYSTEM_BASIC_INFORMATION { ULONG Unknown; ULONG MaximumIncrement; ULONG PhysicalPageSize; ULONG NumberOfPhysicalPages; ULONG LowestPhysicalPage; ULONG HighestPhysicalPage; ULONG AllocationGranularity; ULONG LowestUserAddress; ULONG HighestUserAddress; ULONG ActiveProcessors; UCHAR NumberProcessors; }SYSTEM_BASIC_INFORMATION,*PSYSTEM_BASIC_INFORMATION; <font color="gray][ LightElf</font><!--color--><font color="gray]: Как построить буфер из произвольного списка страниц? ]</font><!--color--> Скорее всего никак, в смысле с помощью экспортируемых ядром функций. Тебе придется разобраться как IoAllocateMdl, MmCreateMdl и т.п. это делают. <font color="gray][ LightElf</font><!--color--><font color="gray]: как создать пустой MDL, то есть не связанный с какой-либо памятью. ]</font><!--color--> Тоже скорее всего никак, ибо MDL есть описание некоторого кол-ва страниц памяти, а если этого кол-ва нет, то и описывать нечего. <font color="gray][ LightElf</font><!--color--><font color="gray]: как привязать MDL к виртуальному адресу? ]</font><!--color--> Привязка происходит в момент формирования MDL.
[Four-F: ZwQuerySystemInformation, SystemBasicInformation,...] А оно разве из драйвера доступно? Или "Нельзя, но если очень хочется, то можно..."? А по сути: ни фига не понимаю, чего делает IoAllocateMdl. Делаем такое: IoAllocMdl(NULL, 16384, FALSE, FALSE, NULL) получаем MDL, у которой в таблице страниц загадочные числа, а-ля 80c1a178, 80c15318, 00002501, 00001d42... Что это, Бэрримор? Первые два числа никак не тянут на физический адрес страницы, ибо у компа всего 64мега памяти. Последние два тоже какие-то странные... При этом в заголовке MDL, как и положено, лежат внятные числа, все пучком...
IoAllocMdl не выделяет память под буфер. Она 1. Выделяет память под дескриптор буфера (MDL) с учетом его страничной организации. Минимальный размер этого буфера - sizeof(MDL) + 4 * 0x17 (жуткий хардкод ). 2. Заполняет таблицу PFN (номера физических страниц), отображенных на виртуальный адрес, переданный первым параметром ( для вытесняемой памяти ) - в Вашем случае в таблице PFN просто мусор - MDL ничего не описывает Чтобы выделить буфер и получить дескриптор, можно действовать примерно так: PVOID p = ExAllocatePool(NonPagedPool, 4 * PAGE_SIZE ); PMDL mdl = IoAllocateMdl(p, 4 * PAGE_SIZE, 0, 0, 0); MmBuildMdlForNonPagedPool(mdl);
Спасибо TarasCo за пояснение. Мне не нужно выделять буфер - он уже выделен и сделан non-pageble. Но: я не знаю его линейный адрес (такое вот хреновое лето), но знаю что в нем будет лежать сигнатура. Поэтому я хочу: 1) мапя по одной страничке (с помощью MmMapIoSpace/ MmUnmapIoSpace) просмотреть всю физическую память в поисках страниц с сигнатурой. 2) создать MDL, руками заполнить ее номерами физических страниц, найденных на предыдущем этапе. 3) прикрутить полученную MDL к некоторому линейному адресу. Пока вытанцовывается такая картина: 1) через MmAllocateMappingAddress резервируем кусок адресного пространства нужного размера. 2) через IoAllocateMdl создаем для него MDL, заполняем его ручками 3) с помощью MmMapLockedPagesWithReservedMapping прикручиваем страницы MDL к зарезервированному на первом этапе адресному пространству. Осталось разобраться с содержимым MDL
А зачем такие сложности? Если ты пробежишь по памяти и выяснишь номера физическиз страниц, где лежит твой буфер, а затем сам создашь MDL, то дальше можно пойти документированным путем: MmMapLockedPages - система сама найдет диапазон виртуальных адресов, куда можно отобразить твой набор и проделает это. Зачем делать чужую работу? Кроме того, просмотреть физическую память можно без MmMapIoSpace. Есть секция //Device//PhysicalMemory - туда замеплена физическая память и смещение от начала секции соответсвует смещению от 0 линейного адреса.
От 0 физического адреса наверно? Как? Просто выделить место из nonpageble pool нужного размера и руками создать заголовок?
Чето мой пост не дошел или меня забанили? От 0 физического адреса наверно? так точно Как? Просто выделить место из nonpageble pool нужного размера и руками создать заголовок? MDL можешь как хочешь сляпать. Но таблицу PFN нужно руками заполнять. Нужно заметить, PFN - это не физический адрес страницы. Вычисляется он примерно так: #define PHYSICAL_ADDRESS_TO_PFN(addr)(((ULONG)addr << 3) >> 15) на других платформах, возможно, по другому
Вот! Это собственно и есть ключевой аспект Теперича я знаю кто есть ху. Спасибо! Я еще приду с новыми вопросами
<font color="gray][ LightElf</font><!--color--><font color="gray]: ZwQuerySystemInformation... А оно разве из драйвера доступно? ]</font><!--color--> Да. Без проблем. <font color="gray][ TarasCo</font><!--color--><font color="gray]: на других платформах, возможно, по другому ]</font><!--color--> #define MI_CONVERT_PHYSICAL_TO_PFN(Va) (((ULONG)Va << 2) >> (PAGE_SHIFT + 2)) <font color="gray][ LightElf</font><!--color--><font color="gray]: Как? Просто выделить место из nonpageble pool нужного размера и руками создать заголовок? ]</font><!--color--> Вобщем да. Код (Text): PMDL MDL, PVOID Base, SIZE_T Length SIZE_T MdlSize; MdlSize = MmSizeOfMdl( Base, Length ); MDL = (PMDL) ExAllocatePoolWithTag( NonPagedPool, MdlSize, 'ldmM' ); MmInitializeMdl( MDL, Base, Length ); В качестве Base указываешь любой адрес, в качестве Length - кол-во твоих страниц * PAGE_SIZE. Дальше в массив страниц заносишь номера твоих физических страниц, т.е. PFN = физический адрес >> PAGE_SHIFT. Это практически тоже самое, что делает MmCreateMdl . Но ты так не делай Ибо как система будет воспринимать такой МДЛ я не знаю. Ведь эти страницы на самом деле отображены на другие виртуальные адреса и что ты будешь указывать в качестве Base? И что будет в случае если страницы будут маленькие и большие?
Ну спасибо Я собственно потому и хочу использовать MmAllocateMappingAddress чтобы иметь виртуальный адрес за которым заведомо нет никакой памяти. Тогда я смогу его использовать как Base направо-налево. Ну а то, что физические страницы имеют несколько алиасных виртуальных адресов - на то вроде бы и сделана виртуальная память. А вот этого точно не будет. Все страницы будут по 4кб.
Но ты так не делай Ибо как система будет воспринимать такой МДЛ я не знаю. Ведь эти страницы на самом деле отображены на другие виртуальные адреса и что ты будешь указывать в качестве Base? И что будет в случае если страницы будут маленькие и большие? А чего такого то? Физические страницы можно отобразить хоть на (ну не знаю... ) ну хоть на 2 Различных адресных диапазона. Им то по барабану. 2 LightElf: Напиши о результатах, интересно ж
<font color="gray][ TarasCo</font><!--color--><font color="gray]: Физические страницы можно отобразить хоть на... ]</font><!--color--> Отобразить то можно, но они же не отображены, когда мы МДЛ руками делаем. Система то его делает из уже отображенных страниц. Вобщем, всё это очень сильный хак, а сильно думать лень, что будет. Вот поэтому "ты так не делай"
По идее, если для MDL, у которого BaseVa = 0 и все (в том числе таблица PFN) будет верно заполнена, вызвать MmMapLockedPages (2 Four-F: взгляни туда же, откуда определение MI_CONVERT_PHYSICAL_TO_PFN ), то ядро само ваыделит достаточный непрерывный диапазон виртуальной памяти для отображения физических страниц. Это конечно хак, но не такой уж сильный . А вот использование MmAllocateMappingAddress на мой взгляд лдишнее ( и по сути тот же хак и андок)
<font color="gray][ TarasCo</font><!--color--><font color="gray]: 2 Four-F: взгляни туда же... ]</font><!--color--> Да хрен с ним. Своего геморра хватает
В общем всем спасибо. Похоже что метода работает. На реальном драйвере пока не проверял, наваял кролика простейшего (через один IOCTL выделяет locked буфер и заполняет его сигнатурой, через другой - сканит физпамять и создает искомый маппинг). Посмотрим потом, как себя это будет вести на боевой системе - может в стрессе система подлянку какую выкинет. последовательность действий такая: ptr = MmAllocateMappingAddress(size, tag); pMdl = IoAllocateMdl(ptr, size, FALSE, FALSE, NULL); Дальше заполняем PFN и делаем MmMapLockedPages. Так что вот такие извращения для тривиальной вроде бы задачи.
Никак не определяю - я заведомо это знаю. То есть в моем случае я точно знаю, что страницы, составляющие искомый буфер, локед