En mi programa en C++ (en Windows), estoy asignar un bloque de memoria y puede asegurarse de que permanece bloqueado (a canje y contigua) en la memoria física (es decir, utilizando VirtualAllocEx(), MapUserPhysicalPages() etc.)
No, realmente no puede asegurarse de que permanezca bloqueado. ¿Qué pasa si su proceso se bloquea o sale antes de tiempo? ¿Qué pasa si el usuario lo mata? Esa memoria se reutilizará para otra cosa, y si su dispositivo todavía está haciendo DMA, eso eventualmente dará como resultado la pérdida/corrupción de datos o una comprobación de errores (BSOD).
Además, MapUserPhysicalPages
es parte de Windows AWE (Address Windowing Extensions), que es para manejar más de 4 GB de RAM en versiones de 32 bits de Windows Server. No creo que estuviera destinado a ser usado para hackear DMA en modo usuario.
1. ¿Hay alguna manera de que pueda traducir la dirección virtual a la física dentro de mi programa, en modo USUARIO?
hay conductores que le permiten hacer esto, pero no se puede programar DMA de modo de usuario en Windows y aún así tener un sistema estable y seguro. Dejar que un proceso que se ejecuta como una cuenta de usuario limitada leer/escribir en la memoria física permite que ese proceso sea el propietario del sistema. Si se trata de un sistema único o un prototipo, probablemente sea aceptable, pero si espera que otras personas (especialmente los clientes que pagan) usen su software y su dispositivo, debe escribir un controlador.
2. Si no es así, no puedo encontrar a cabo este virtual de modo que la cartografía física única en el kernel. Supongo que significa que tengo que escribir un controlador para hacerlo ...
Esa es la forma recomendada para abordar este problema.
¿Conoce algún controlador/DLL/API disponible que pueda usar, con el que se conectará mi aplicación (programa) para hacer la traducción?
Puede usar un MDL (Memory Descriptor List) para bloquear la memoria arbitraria, incluidos los almacenamientos intermedios de memoria que pertenecen a un proceso en modo de usuario, y traducir sus direcciones virtuales en direcciones físicas. También puede hacer que Windows cree temporalmente una MDL para el búfer pasado a una llamada al DeviceIoControl
utilizando METHOD_IN_DIRECT
o METHOD_OUT_DIRECT
.
Tenga en cuenta que las páginas contiguas en el espacio de direcciones virtuales casi nunca son contiguas en el espacio de direcciones físicas. Es de esperar que su dispositivo esté diseñado para manejar eso.
3. En caso de que voy a tener que escribir el conductor a mí mismo, ¿cómo lo hago esta traducción? ¿Qué funciones uso? ¿Es mmGetPhysicalAddress()? ¿Como lo uso?
Hay mucho más para escribir un controlador que simplemente llamando a unos API. Si va a escribir un controlador, le recomendaría leer todo el material relevante que pueda de MSDN y OSR. Además, mira los ejemplos en el Windows Driver Kit.
4. Además, si entiendo correctamente, mmGetPhysicalAddress() devuelve la dirección física de una dirección base virtual que está en el contexto del proceso de llamada. Pero si el proceso de llamada es el controlador, y estoy usando mi aplicación para llamar al controlador para esa función, estoy cambiando los contextos y ya no estoy en el contexto de la aplicación cuando se llama a la rutina mmGetPhysicalAddress ... entonces ¿Cómo traduzco la dirección virtual en el espacio de memoria de la aplicación (modo de usuario), no el controlador?
Los conductores no son procesos. Un controlador se puede ejecutar en el contexto de cualquier proceso, así como en varios contextos elevados (controladores de interrupción y DPC).
Tengo curiosidad, ¿qué podía hacer un dispositivo externo con una dirección de memoria física? – jyoung
Sin entrar en detalles, es un dispositivo incorporado que tiene acceso directo a la RAM de la máquina, pero no tiene conocimiento de las asignaciones de OS (razón por la cual una dirección virtual o el uso de un objeto de memoria compartida no funcionará). –