在Linux内核空间中实现"魔术环形缓冲区"?

3

我知道"魔术环形缓冲区"技巧,它涉及在进程的地址空间中镜像底层缓冲区,以允许数据块通过单个memcpy()进行排队,而不必担心换行。

我想在Linux内核模块中实现相同的功能。假设我使用dma_alloc_coherent()创建了一个缓冲区,其虚拟地址为V,长度为N。如何创建映射,以便其虚拟地址[V+N,V+2N)映射到与[V,V + N)相同的底层页面?

注意:这是在32位ARM Linux下进行的。


2
kfifo.ckfifo.h是一个支持常量大小元素且不需要任何MMU帮助的版本。它们在内核中更为常见。 - undefined
谢谢!我觉得这对我的应用程序来说是可行的,而且我认为镜像缓冲区是不必要的。 - undefined
1个回答

0

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);
    ...

据我所见,目前没有类似的API用于一致的DMA内存。如果你知道你的架构如何处理这个问题,你可能可以重新映射dma_alloc_coherent()返回的页面。
请注意,如果你使用多个虚拟地址来修改相同的物理地址,某些架构可能会出现缓存问题;即使你成功映射了它,你还需要检查在你特定的架构中,一致的DMA内存是否可缓存。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接