В моей программе на C ++ (в Windows) я выделяю блок памяти и могу убедиться, что он остается заблокированным (неразделенным и непрерывным) в физической памяти (т.е. используя VirtualAllocEx (), MapUserPhysicalPages () и т. Д.) .
Нет, вы не можете гарантировать, что он останется заблокированным. Что если ваш процесс завершится сбоем или завершится раньше? Что если пользователь убьет это? Эта память будет использоваться повторно для чего-то другого, и если ваше устройство все еще выполняет DMA, это в конечном итоге приведет к потере / повреждению данных или проверке ошибок (BSOD).
Кроме того, MapUserPhysicalPages
является частью Windows AWE (Address Windowing Extensions), которая предназначена для обработки более 4 ГБ ОЗУ в 32-разрядных версиях Windows Server. Я не думаю, что он был предназначен для взлома DMA в пользовательском режиме.
1. Можно ли как-нибудь перевести виртуальный адрес в физический адрес моей программы в режиме USER?
Существуют драйверы, которые позволяют вам это делать, но вы не можете запрограммировать DMA из пользовательского режима в Windows и при этом иметь стабильную и безопасную систему. Разрешение процессу, выполняемому как физическая память с возможностью чтения / записи с ограниченной учетной записью, позволяет этому процессу владеть системой. Если это для одноразовой системы или прототипа, это, вероятно, приемлемо, но если вы ожидаете, что другие люди (особенно платящие клиенты) будут использовать ваше программное обеспечение и ваше устройство, вам следует написать драйвер.
2. Если нет, я могу обнаружить это виртуальное физическое отображение только в режиме KERNEL. Я думаю, это означает, что мне нужно написать драйвер для этого ...?
Это рекомендуемый способ решения этой проблемы.
Знаете ли вы о каком-либо легкодоступном драйвере / DLL / API, который я могу использовать, с которым мое приложение (программа) будет взаимодействовать для выполнения перевода?
Вы можете использовать MDL (список дескрипторов памяти) , чтобы заблокировать произвольную память, включая буферы памяти, принадлежащие процессу пользовательского режима, и преобразовать его виртуальные адреса в физические адреса. Windows также может временно создать MDL для буфера, переданного в вызов DeviceIoControl
, используя METHOD_IN_DIRECT
или METHOD_OUT_DIRECT
.
Обратите внимание, что смежные страницы в виртуальном адресном пространстве почти никогда не являются смежными в физическом адресном пространстве. Надеюсь, ваше устройство предназначено для этого.
3. Если мне придется написать драйвер самостоятельно, как мне сделать этот перевод? какие функции я использую? Это mmGetPhysicalAddress ()? Как мне его использовать?
Для написания драйвера гораздо больше, чем просто вызов нескольких API. Если вы собираетесь написать драйвер, я бы порекомендовал прочитать как можно больше соответствующих материалов из MSDN и OSR . Также посмотрите на примеры из Windows Driver Kit .
4. Кроме того, если я правильно понимаю, mmGetPhysicalAddress () возвращает физический адрес виртуального базового адреса, который находится в контексте вызывающего процесса. Но если вызывающий процесс является драйвером, и я использую свое приложение для вызова драйвера для этой функции, я меняю контексты и больше не нахожусь в контексте приложения, когда вызывается подпрограмма mmGetPhysicalAddress ... как перевести виртуальный адрес в область памяти приложения (пользовательский режим), а не в драйвер?
Драйверы не являются процессами. Драйвер может выполняться в контексте любого процесса, а также в различных контекстах с повышенными правами (обработчики прерываний и DPC).