我有一个简单的程序,尝试访问用户空间中的物理内存,内核在其中存储了第一个struct页面。在64位计算机上,此地址为:
我正在尝试通过用户空间中的mmap访问此物理地址。但是以下代码使内核崩溃。
int *addr; if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0 ) { printf("Error opening file. \n"); close(fd); return (-1); } /* mmap. address of first struct page for 64 bit architectures * is 0x0000620000000000. */ addr = (int *)mmap(0, num*STRUCT_PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0x0000620000000000); printf("addr: %p \n",addr); printf("addr: %d \n",*addr); /* CRASH. */
我想我已经找到了问题-与x86上的/ dev / mem内存映射保护有关。
请参阅此LWN文章:“ x86:通过配置选项引入/ dev / mem限制” http://lwn.net/Articles/267427/
CONFIG_NONPROMISC_DEVMEM
现在(我在最近的3.2.21内核上对此进行了测试),config选项似乎称为CONFIG_STRICT_DEVMEM。
我更改了内核配置:
$ grep DEVMEM .config # CONFIG_STRICT_DEVMEM is not set $
当上述prg与 先前的 内核一起运行时,使用CONFIG_STRICT_DEVMEM SET设置:dmesg显示:
[29537.565599] Program a.out tried to access /dev/mem between 1000000->1001000. [29537.565663] a.out[13575]: segfault at ffffffff ip 080485bd sp bfb8d640 error 4 in a.out[8048000+1000]
这是由于内核保护。
重建内核(使用CONFIG_STRICT_DEVMEM UNSET )并运行上述prg时:
# ./a.out mmap failed: Invalid argument #
这是因为’offset’参数> 1 MB(在x86上无效)(当时为16MB)。
将mmap偏移量控制在1 MB以内:
# ./a.out addr: 0xb7758000 *addr: 138293760 #
有用!有关详细信息,请参见上面的LWN文章。
在具有PAT支持(页面属性表)的x86体系结构上,内核仍然阻止DRAM区域的映射。内核源代码中提到的原因是:
This check is nedded to avoid cache aliasing when PAT is enabled
此检查将导致与上述错误类似的错误。例如:
Program a.out tried to access /dev/mem between [mem 68200000-68201000].
可以通过禁用PAT来消除此限制。可以通过在启动时将“ nopat”参数添加到内核命令行来禁用PAT。