【问题标题】:"Magic ring buffer" implementation in Linux kernel space?Linux内核空间中的“魔术环形缓冲区”实现?
【发布时间】:2017-08-31 19:23:30
【问题描述】:

我知道 "magic ring buffer" 技巧涉及在进程地址空间中镜像底层缓冲区,以允许数据块与单个 memcpy() 一起排队,而不必担心回绕。

我想在 Linux 内核模块中完成同样的事情。假设我有一个用dma_alloc_coherent() 创建的缓冲区,它的虚拟地址是V,它的长度是N。如何创建映射,使其虚拟地址 [V+N,V+2N) 映射到与 [V,V+N) 相同的底层页面?

注意:这是在 32 位 ARM Linux 中。

【问题讨论】:

  • kfifo.ckfifo.h 是无需任何 MMU 帮助即可支持恒定大小元素的版本。它们在内核中更为常见。
  • 谢谢!我认为这适用于我的应用程序,并且我认为镜像缓冲区不是必需的。

标签: c linux-kernel arm linux-device-driver circular-buffer


【解决方案1】:

drivers/firewire/ohci.c 将异步接收环形缓冲区的某些页面映射两次,以便更轻松地访问接收到的环绕数据包:

    for (i = 0; i < AR_BUFFERS; i++) {
            ctx->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32);
            ...
            dma_addr = dma_map_page(ohci->card.device, ctx->pages[i],
                                    0, PAGE_SIZE, DMA_FROM_DEVICE);
            ...
    }
    for (i = 0; i < AR_BUFFERS; i++)
            pages[i]              = ctx->pages[i];
    for (i = 0; i < AR_WRAPAROUND_PAGES; i++)
            pages[AR_BUFFERS + i] = ctx->pages[i];
    ctx->buffer = vmap(pages, ARRAY_SIZE(pages), VM_MAP, PAGE_KERNEL);
    ...

据我所知,没有用于一致性 DMA 内存的类似 API。如果您知道您的架构如何处理此问题,您或许可以重新映射 dma_alloc_coherent() 返回的页面。

请注意,如果您使用多个虚拟地址修改同一个物理地址,某些架构的缓存可能会出现问题;即使您设法映射它,您也必须检查是否可以在您的特定架构中缓存一致的 DMA 内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多