2017-04-06 10 views
1

私は、データのチャンクがラップアラウンドを気にすることなく、単一のmemcpy()でエンキューすることができるようにするプロセスのアドレス空間に根本的なバッファをミラーリングする必要"magic ring buffer"トリックを知っています。Linuxカーネル空間での "Magic ring buffer"の実装?

私は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メモリがキャッシュ可能かどうかをチェックする必要があります。

関連する問題