linux 用户空间映射,在Linux中如何从用户空间访问物理地址?

busybox devmem

busybox devmem是mmaps的小型CLI实用程序/dev/mem。

您可以通过以下方式在Ubuntu中获取它: sudo apt-get install busybox

用法:从物理地址读取4个字节0x12345678:

sudo busybox devmem 0x12345678

写入0x9abcdef0该地址:

sudo busybox devmem 0x12345678 w 0x9abcdef0

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

mmap MAP_SHARED

映射时/dev/mem,您可能要使用:

open("/dev/mem", O_RDWR | O_SYNC);

mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)

MAP_SHARED 使写操作立即进入物理内存,这使观察起来更容易,并且对硬件寄存器写操作更有意义。

CONFIG_STRICT_DEVMEM 和 nopat

要/dev/mem查看和修改内核v4.9上的常规RAM,必须首先:

禁用CONFIG_STRICT_DEVMEM(在Ubuntu 17.04上默认设置)

传递nopatx86 的内核命令行选项

没有这些端口,IO端口仍然可以工作。

另请参见:/ dev / mem的mmap失败,且virt_to_phys地址的参数无效,但是地址是页面对齐的

缓存刷新

如果您尝试写入RAM而不是寄存器,则CPU可能会缓存内存:如何在Linux中刷新CPU缓存以获取地址空间区域?而且我看不到一种非常方便/简便的方法来刷新它或将该区域标记为不可缓存:

如何使用O_DIRECT将内核空间内存(物理地址)写入文件?

如何在Linux中刷新地址空间区域的CPU缓存?

是否可以在用户空间上在Linux上分配不可缓存的内存块?

因此,也许/dev/mem不能可靠地用于将内存缓冲区传递给设备吗?

不幸的是,这在QEMU中无法观察到,因为QEMU不模拟缓存。

如何测试

现在是有趣的部分。以下是一些不错的设置:

用户区内存

volatile在用户态进程上分配变量

使用/proc//maps+ 获取物理地址/proc//pagemap

使用修改物理地址上的值devmem,并观察用户态过程的反应

内核内存

用以下方式分配内核内存 kmalloc

获取物理地址virt_to_phys并将其传回用户空间

修改物理地址 devmem

从内核模块查询值

IO内存和QEMU虚拟平台设备

创建具有已知物理寄存器地址的平台设备

用于devmem写入寄存器

手表printf从虚拟设备中出来以响应