Linux用户程序如何访问物理内存
Contents
用户态的程序都是在内存保护模式下使用内存,无法直接访问物理内存。同时用户程序使用的地址都是逻辑地址,而不是物理地址。这些逻辑地址对应的物理内存在哪里,用户进程本身并不知道。
如果用户程序想要访问物理内存,就需要通过内核实现。本文介绍基于内存模块的方式,实现Linux
中用户态程序访问所有物理内存。
系统环境
- 发行版:
centos7.5
(Virtual Box虚拟机) - 内核版本:3.10.0-862.14.4.el7.x86_64
- 处理器:
Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
- 内存:
4GB
内核模块的编写
在3.10.0-862.14.4.el7.x86_64版本的内核上,其实已经有相关模块(内核代码)实现了用户程序访问物理内存的功能,其提供的接口包括如下几个:
- /dev/mem
- /dev/crash
这些模块的实现原理都类似:通过文件读写的方法,实现物理内存地址的访问。将物理地址,作为参数poff
传递。
|
|
在内核代码中,是无法直接访问物理地址的,代码能访问的都是逻辑地址。此时我们需要先将物理地址转换成逻辑地址,才能在代码中对地址读写。
物理地址转换成逻辑地址方法map_virtual
的原理:
(1)根据物理地址,计算出对应的页面号
|
|
(2)将页面号找到对应的页面指针
|
|
(3)通过kmap
映射成逻辑地址
|
|
基于以上原理,本文实现了一个内核模块my_crash.ko
,插入模块后,系统上会创建一个设备文件/dev/mycrash
|
|
注意:
/dev/mycrash
是在/dev/crash
的基础上修改而来的,因为/dev/crash
中没有考虑整个系统的物理地址大小,其crash_llseek
实现也不满足需求。
物理内存数据查看
这里我们就是用了http://ilinuxkernel.com/?p=1248中提到的fileview
工具来查看物理内存中的实际数据,物理地址可以手工输入。
fileview工具简要用法
- 输入回车键,接着出现
Address
提示,可以输入要查看的物理地址,然后回车键确认,即可查看物理内存的信息。 Q
和q
: 以8字节显示结果W
和w
: 以2字节显示结果D
和d
: 以4字节显示结果B
和b
: 以1字节显示结果ESC
: 退出程序
查看物理内存示例
我们通过crash
寻找一个内核变量的物理地址:
|
|
saved_command_line
变量的物理地址是11ff39f00
,我们通过`fileview查看一下,看物理内存上的信息是否正确:
代码
本文中的模块和fileview
代码:access_physical_memory.tar.gz