ioremap 后的内存访问非常慢

Dav*_*dia 5 memory performance kernel driver linux-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;
}
Run Code Online (Sandbox Code Playgroud)

我加载驱动程序,并检查 dmesg。它报告:

[memdriver] init
[memdriver] ioremap() took 76268 usec
[memdriver] memset() took 12622779 usec
Run Code Online (Sandbox Code Playgroud)

这是 memset 的 12.6 秒。这意味着 memset 以81 MB/sec 的速度运行。为什么地球这么慢?

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

编辑:

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


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

Eri*_*nen 5

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

您可能想要kmallocvmalloc。在通常的 参考 材料将解释每一个的能力。