ver uso tengo sistema saber que memoria listar liberar informacion dispositivos como comandos comando caracteristicas linux memory arm memory-address memory-mapping

uso - ¿Cómo acceder a las direcciones físicas desde el espacio de usuario en Linux?



ver memoria ram linux terminal (2)

busybox devmem

busybox devmem es una pequeña utilidad de CLI que mmaps /dev/mem .

Puedes conseguirlo en Ubuntu con: sudo apt-get install busybox

Uso: lea 4 bytes desde la dirección física 0x12345678 :

sudo busybox devmem 0x12345678

Escriba 0x9abcdef0 en esa dirección:

sudo busybox devmem 0x12345678 w 0x9abcdef0

Fuente: https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85

MAP_SHARED

Cuando mmapping /dev/mem , es probable que desee utilizar:

open("/dev/mem", O_RDWR | O_SYNC); mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)

MAP_SHARED hace que las escrituras vayan a la memoria física inmediatamente, lo que hace que sea más fácil de observar, y tiene más sentido para las grabaciones de registros de hardware.

CONFIG_STRICT_DEVMEM y nopat

Para usar /dev/mem para ver y modificar la memoria RAM regular en kernel v4.9, debe puño:

  • deshabilitar CONFIG_STRICT_DEVMEM (establecido por defecto en Ubuntu 17.04)
  • pasar la opción de línea de comando del kernel nopat para x86

Los puertos IO todavía funcionan sin esos.

Ver también: mmap de / dev / mem falla con un argumento inválido para la dirección de virt_to_phys, pero la dirección está alineada con la página

Lavado de caché

Si intenta escribir en RAM en lugar de en un registro, la memoria puede ser almacenada en la memoria caché por la CPU: ¿Cómo vaciar el caché de la CPU para una región de espacio de direcciones en Linux? y no veo una forma muy portátil / fácil de enjuagarlo o marcar la región como incableable:

¿Entonces /dev/mem no se puede usar de manera confiable para pasar memorias intermedias de memoria a los dispositivos?

Esto no se puede observar en QEMU lamentablemente, ya que QEMU no simula cachés.

Cómo probarlo

Ahora viene la parte divertida. Aquí hay algunas configuraciones geniales:

  • Memoria de usuario
    • asignar variable volatile en un proceso de usuario
    • obtener la dirección física con /proc/<pid>/maps + /proc/<pid>/pagemap
    • modifique el valor en la dirección física con devmem , y observe cómo el proceso de userland reacciona
  • Memoria Kernelland
    • asignar memoria de kernel con kmalloc
    • obtener la dirección física con virt_to_phys y pasarla a userland
    • modificar la dirección física con devmem
    • consultar el valor del módulo kernel
  • Dispositivo de plataforma virtual IO mem y QEMU
    • crear un dispositivo de plataforma con direcciones de registros físicos conocidos
    • use devmem para escribir en el registro
    • Ver printf s salir del dispositivo virtual en respuesta

En un sistema basado en ARM que ejecuta Linux, tengo un dispositivo cuya memoria está asignada a una dirección física. Desde un programa de espacio de usuario donde todas las direcciones son virtuales, ¿cómo puedo leer el contenido de esta dirección?


Puede asignar un archivo de dispositivo a una memoria de proceso de usuario mediante la llamada al sistema mmap(2) . Por lo general, los archivos del dispositivo son asignaciones de memoria física al sistema de archivos. De lo contrario, tiene que escribir un módulo kernel que crea dicho archivo o proporciona una forma de asignar la memoria necesaria a un proceso de usuario.

Otra forma es reasignar partes de / dev / mem a la memoria de un usuario.

Editar: Ejemplo de mmaping / dev / mem (este programa debe tener acceso a / dev / mem, por ejemplo, tener derechos de root):

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> int main(int argc, char *argv[]) { if (argc < 3) { printf("Usage: %s <phys_addr> <offset>/n", argv[0]); return 0; } off_t offset = strtoul(argv[1], NULL, 0); size_t len = strtoul(argv[2], NULL, 0); // Truncate offset to a multiple of the page size, or mmap will fail. size_t pagesize = sysconf(_SC_PAGE_SIZE); off_t page_base = (offset / pagesize) * pagesize; off_t page_offset = offset - page_base; int fd = open("/dev/mem", O_SYNC); unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base); if (mem == MAP_FAILED) { perror("Can''t map memory"); return -1; } size_t i; for (i = 0; i < len; ++i) printf("%02x ", (int)mem[page_offset + i]); return 0; }