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从虚拟设备中出来以响应