当前位置: 首页 > 面试题库 >

如何在不崩溃Linux内核的情况下访问mmaped / dev / mem?

萧亦
2023-03-14
问题内容

我有一个简单的程序,尝试访问用户空间中的物理内存,内核在其中存储了第一个struct页面。在64位计算机上,此地址为:

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

我正在尝试通过用户空间中的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选项似乎称为CON​​FIG_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。



 类似资料:
  • 问题内容: 我已经构建了两个内核模块,其中一个是net_device。我的net_device模块A依赖于模块B,模块B提供了一些额外的控制机制来导出设备信息。 我希望模块B能够调用模块A中的“ xmit”函数。因此,如果我简单地从A导出符号,则模块B将依赖于模块A。这显然会产生“死锁”依赖性情况。 有没有人有解决这个问题的经验?如何正确导出A中的“ xmit”函数并让B使用它? 问题答案: 您可

  • 问题内容: 我是Linux内核的新手。 我知道有两个上下文 1.进程上下文,在用户空间或内核空间中运行(例如:作为系统调用的一部分) 2.中断上下文 在什么情况下运行内核线程(与ex:flush任务无关的任何用户线程)? 除了Linux内核中的Process和Interrupt上下文之外,还有其他上下文吗? 问题答案: 内核线程在内核空间中的进程上下文中运行。虽然也有一些内核线程可以处理中断。它们

  • 问题内容: 据我了解,initrd是一个小图像,可以在RAM中加载。它用于引导带有所有可加载模块的完整内核。在此过程中,我们需要vmlinuz内核映像,它是bzImage的重命名版本。 是否可以在不创建initrd映像的情况下引导内核? 问题答案: initrd / initramfs是可选的,不是必需的。bzImage是纯内核映像,可以由引导加载程序直接引导。但是,可能需要执行某些任务(通常需要

  • 我复制了gRPC helloworld示例中粘贴的gRPC服务器。 它开始侦听指定端口中的RPC,但当我使用复制粘贴的客户端调用RPC时,它会崩溃,出现“中止(内核转储)”,在客户端收到错误消息“Endpoint read failed”。 我尝试通过在RPC函数实现中包含一些输出语句来调试它,但执行从未达到目的。 没有其他错误消息,是否有一些标志使故障更详细,以便调试?

  • 问题内容: 现在,我需要实时获取NIC的状态(向上或向下)。这意味着当NIC在阻塞循环中上下时,我必须捕获内核中断。 我的第一个愚蠢的方法是检查 / sys / class / net / eth0 / operstate 或使用 ioctl 在循环中每隔100ms获取一次ifflag。但是100毫秒对于应用程序重新路由流量太长,而且每100毫秒轮询一次内核不是一个好主意。 一旦我注意到可以在块模

  • 问题内容: 注意:我在使用React Native时遇到了这个特定的问题,但是我想这也同样适用于React。 我有一个使用React.Component构建的React组件。我不需要设置状态,但是我有道具。我建议的语法如下: 我知道我可以使用函数来构造此组件,如下所示: 但是我更喜欢前者,因为我的组件会增长,可能会有状态等,我只想以相似的方式构建所有组件。 现在,我的linter抱怨拥有一个无用的