2017-04-06 63 views
1

我知道了"magic ring buffer"把戲,涉及鏡像基礎緩衝區的進程的地址空間,讓數據塊與單個memcpy()入隊,而不必擔心迴繞的。Linux內核空間中的「魔術環緩衝區」實現?

我想完成同樣的事情,但在Linux內核模塊。假設我有dma_alloc_coherent()創建的緩衝器,其虛擬地址爲V其長度爲N。如何創建映射,使其虛擬地址[V+N,V+2N)映射到與[V,V+N)相同的底層頁面?

注:這是在32位ARM Linux操作系統。

+2

[kfifo.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/libkfifo.c)和[kfifo.h](https: //git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/kfifo.h)是支持固定大小的元素沒有任何MMU幫助版本。它們在內核中更常見。 –

+0

謝謝!我認爲這將適用於我的應用程序,我不認爲鏡像緩衝區是必要的。 –

回答

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

據我所看到的,是一致的DMA沒有類似的API記憶。如果您知道您的架構如何處理此問題,您可以重新映射由dma_alloc_coherent()返回的頁面。

請注意,某些架構可以有自己的緩存,如果你正在使用多個虛擬地址修改同一個物理地址的問題;即使您設法映射它,您也必須檢查連貫的DMA內存是否可以在特定的arch中進行緩存。