本文介绍了如何在不使 Linux 内核崩溃的情况下访问 mmaped/dev/mem?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的程序,试图访问用户空间中的物理内存,内核存储第一个结构页面.在 64 位机器上,这个地址是:

I have a simple program that tries to access the physical memory in user space, where the kernel stores the 1st struct page. On a 64 bit machine this address is:

  • 内核虚拟地址:ffffea0000000000
  • 物理地址:0000620000000000

我试图在用户空间通过 mmap 访问这个物理地址.但是下面的代码会导致内核崩溃.

I am trying to access this physical address through mmap in user space. But the following code crashes the kernel.

int *addr;
if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0 ) {
    printf("Error opening file.
");
    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
",addr);
printf("addr: %d
",*addr); /* CRASH. */

推荐答案

我想我已经找到了问题——它与 x86 上的/dev/mem 内存映射保护有关.

I think I've found the issue -- it's to do with /dev/mem memory mapping protection on the x86.

请参考这篇 LWN 文章:x86:使用配置选项引入/dev/mem 限制"http://lwn.net/Articles/267427/

Pl refer to this LWN article:"x86: introduce /dev/mem restrictions with a config option"http://lwn.net/Articles/267427/

CONFIG_NONPROMISC_DEVMEM

CONFIG_NONPROMISC_DEVMEM

现在(我在最近的 3.2.21 内核上对此进行了测试),配置选项似乎被称为 CONFIG_STRICT_DEVMEM.

Now (i tested this on a recent 3.2.21 kernel), the config option seems to be called CONFIG_STRICT_DEVMEM.

我更改了内核配置:

$ grep DEVMEM .config
# CONFIG_STRICT_DEVMEM is not set
$

当上述 prg 与 previous 内核一起运行时,使用 CONFIG_STRICT_DEVMEM SET:dmesg 显示:

When the above prg was run with the previous kernel, with CONFIG_STRICT_DEVMEM SET:dmesg shows:

[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)并运行上面的程序时:

When the kernel was rebuilt (with the CONFIG_STRICT_DEVMEM UNSET) and the above prg was run :

# ./a.out
mmap failed: Invalid argument
#

这是因为 'offset' 参数 > 1 MB(在 x86 上无效)(它是 16MB).

This is because the 'offset' parameter is > 1 MB (invalid on x86) (it was 16MB).

使 mmap 偏移量在 1 MB 以内后:

After making the mmap offset to be within 1 MB:

# ./a.out
addr: 0xb7758000
*addr: 138293760
#

它有效!有关详细信息,请参阅上面的 LWN 文章.

It works!See the above LWN article for details.

在支持 PAT(页面属性表)的 x86 架构上,内核仍然阻止 DRAM 区域的映射.内核源 是:

On x86 architectures with PAT support (Page Attribute Table), the kernel still prevents the mapping of DRAM regions. The reason for this as mentioned in the kernel source is:

This check is nedded to avoid cache aliasing when PAT is enabled

此检查会导致与上述类似的错误.例如:

This check will cause a similar error to the one mentioned above. For example:

Program a.out tried to access /dev/mem between [mem 68200000-68201000].

可以通过禁用 PAT 来消除此限制.可以通过在启动时向内核命令行添加nopat"参数来禁用 PAT.

This restriction can be removed by disabling PAT. PAT can be disabled by adding the "nopat" argument to the kernel command line at boot time.

这篇关于如何在不使 Linux 内核崩溃的情况下访问 mmaped/dev/mem?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!