ioremap 后的内存访问非常慢

标签 memory linux-kernel driver performance kernel

我正在开发一个 Linux 内核驱动程序,它为用户空间提供一块物理内存。我有驱动程序的工作版本,但目前速度很慢。所以,我退回了几步,尝试制作一个小巧、简单的驱动程序来重现问题。

我在启动时使用内核参数 memmap=2G$1G 保留内存.然后,在驱动程序的 __init函数,我 ioremap一些内存,并将其初始化为已知值。我也输入了一些代码来测量时间:

#define RESERVED_REGION_SIZE    (1 * 1024 * 1024 * 1024)   // 1GB
#define RESERVED_REGION_OFFSET  (1 * 1024 * 1024 * 1024)   // 1GB

static int __init memdrv_init(void)
{
    struct timeval t1, t2;
    printk(KERN_INFO "[memdriver] init\n");

    // Remap reserved physical memory (that we grabbed at boot time)
    do_gettimeofday( &t1 );
    reservedBlock = ioremap( RESERVED_REGION_OFFSET, RESERVED_REGION_SIZE );
    do_gettimeofday( &t2 );
    printk( KERN_ERR "[memdriver] ioremap() took %d usec\n", usec_diff( &t2, &t1 ) );

    // Set the memory to a known value
    do_gettimeofday( &t1 );
    memset( reservedBlock, 0xAB, RESERVED_REGION_SIZE );
    do_gettimeofday( &t2 );
    printk( KERN_ERR "[memdriver] memset() took %d usec\n", usec_diff( &t2, &t1 ) );

    // Register the character device
    ...

    return 0;
}

我加载驱动程序,并检查 dmesg。它报告:
[memdriver] init
[memdriver] ioremap() took 76268 usec
[memdriver] memset() took 12622779 usec

这是 memset 的 12.6 秒。这意味着 memset 运行在 81 MB/秒 .为什么地球这么慢?

这是 Fedora 13 上的内核 2.6.34,它是一个 x86_64 系统。

编辑:

该方案背后的目标是获取一块物理内存并使其可用于 PCI 设备(通过内存的总线/物理地址)和用户空间应用程序(通过调用 mmap ,由驱动程序支持) .然后 PCI 设备会不断地用数据填充这个内存,用户空间应用程序将读取它。如 ioremap这样做是一种糟糕的方式(正如 Ben 在下面建议的那样),我愿意接受其他建议,这些建议将使我能够获得任何可由硬件和软件直接访问的大块内存。我也可以使用较小的缓冲区。

请参阅下面我的最终解决方案。

最佳答案

ioremap分配不可缓存的页面,因为您希望访问内存映射 io 设备。那可以解释你表现不佳的原因。

您可能想要 kmallocvmalloc . usual reference materials将解释每个的能力。

关于ioremap 后的内存访问非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4452400/

相关文章:

c - 释放 OpenCV IplImage 会使应用程序崩溃?

c - 使用指针在结构体中的元素之间移动

kernel - 在 x86 上,当操作系统禁用中断时,它们会消失,还是会排队并 'wait' 以便中断重新启动?

C和64位指针计算

linux - linux 内核驱动程序,取消引用指针和 printk

c++ - 为什么bool和_Bool在内存中占用1个字节只能存储0或1?

c++ - block 内变量的生命周期是多少?

linux - Linux 进程是否可以通过致命信号或调用 `exit(2)` 以外的机制死亡?

linux-kernel - 在 18.04.1-Ubuntu 下的 VirtualBox 中构建最新的 linux 内核时出错

linux-kernel - 在 Linux 中延迟信号处理