2011-08-06 5 views
10

kmallocで割り当てられたバッファをユーザ空間で処理する正しい方法はどれですか?たぶん私はまだメモリマッピングを理解できませんでした...このバッファ(たとえば120バイト)を割り当てるカーネルモジュールを作成し、ユーザー空間プロセスで読み書きします。明らかに、私は文字デバイスを作成し、file_operations構造体にmmapメソッドを実装しました。私の方法がある:mmap:ユーザ空間でのマッピングkmallocで割り当てられたカーネルバッファ

メモリ領域で mem_area点は、モジュールのinitで kmallocが割り当て
static int my_mmap(struct file *filp, struct vm_area_struct *vma) 
{ 
    //printk(KERN_INFO "Allocated virtual memory length = %d", vma->vm_end - vma->vm_start); 

    long unsigned int size = vma->vm_end - vma->vm_start; 

    if (remap_pfn_range(vma, vma->vm_start, 
         __pa(mem_area) >> PAGE_SHIFT, //what about vma->vm_pgoff? 
         size, 
         vma->vm_page_prot) < 0) 
    return -EAGAIN; 

    vma->vm_flags |= VM_LOCKED; 
    vma->vm_ops = &vmops; 
    vma->vm_flags |= VM_RESERVED; 

    my_vm_open(vma); 

    return 0; 
} 

。領域は同じ値で埋められます(たとえば0x10)。すべての作品が、私はこのコードで何かが間違っていると思う:

  1. kmallocがページ揃えではないポインタを返すことができそして、その場合には、私は三番目のパラメータの値が正しいとは思いません実際にはユーザー空間で私は間違った値を読み取ったremap_pfn_rangeの。代わりにすべてが私が__get_free_pageを使用する場合(関数が常にページを揃えたポインタを返すため)、またはkmallocがページを揃えたポインタを返す場合にはすべて機能します。メモリマッピングはPAGE_SIZEの倍数であるメモリ領域で動作するので、kmallocではなくページ全体を割り当てる必要がありますか?

  2. my_mmapが呼び出されると、カーネルはまだいくつかのページを割り当てていますか?私はカスタムmmapメソッドのいくつかの実装を発見したのでこれを尋ねますvma->vm_pgoffremap_pfn_rangeを呼び出すメソッドは3番目のパラメータとして...どのように有用なことができますか?これは最初に割り当てられた新しいページのページフレームですか?私がmy_mmapで行うようなページフレームを3番目のパラメータとして渡すと、ページから始まるvma->vm_pgoffのページを解放する必要がありますか?

  3. しかし、kmallocで割り当てられたバッファをマップするmmapメソッドの実装が見つかりました。バッファを正しくマップするには、remap_pfn_rangeより前に操作(私が今のところundestandしていない)を実行します。 mem_areamemkmallocによって返されたポインタであると仮定し、この方法で初期化されます:

    mem_area=(int *)(((unsigned long)mem + PAGE_SIZE - 1) & PAGE_MASK); 
    

のでmem_areamemの同じ値が含まれていmemがそう整列ページである場合にのみ、IS先頭にポインタが含まれている必要があります次のページのしかし、この操作で、remap_pfn_rangeの3番目のパラメータとして渡すと、値__pa(mem_area) >> PAGE_SHIFTのマッピングがうまく機能します。どうして?

ありがとうございました!

+0

私は同様の質問がありますが、ブートパラメータ 'mmap'を使用しています:http://stackoverflow.com/q/12790382/143897?あなたの発見のいくつかを提供できますか?ありがとう。 –

+0

ここでvm_operations_struct.faultにページフォールトハンドラは必要ありませんか? –

+0

最小限の実行可能な例:https://stackoverflow.com/questions/10760479/how-to-mmap-a-linux-kernel-buffer-to-user-space/45645732#45645732 –

答えて

6
  1. はい、全ページ数を割り当てる必要があります。

  2. いいえ、カーネルはページを割り当てていません。 vm->vm_pgoffはマッピングされているデバイス内で要求されたオフセットです。これは、ユーザ空間mmap()コールの最後のパラメータで、バイトからページに変換されます。おそらく、memまたはkmem mmapの実装を見ているでしょう。この場合、オフセットは、ユーザー空間がマップしたい物理ページまたは線形ページを表します。

  3. これは、kmalloc()割り当てられたバッファ内にページアラインされたバッファを割り当てているだけです。中型の人を切り取って、あなたがすでに推測しているように、あなたは__get_free_pages()を使う方が良いです。

マップするサイズがバッファを超えないことをテストする必要があります。

+0

アンカのためのcafありがとう!私はまだポイント2を理解していません...私は 'mem'や' kmem'の実装を見ませんでしたが、Linuxデバイスドライバの本で見つけました...今、私は 'vma-> vm_pgoff'がマッピングされているデバイス内のオフセットですが、第3のパラメータ 'vma-> vm_pgoff'として' remap_pfn_range'に渡すと、デバイスのどのメモリがマッピングされていますか? – MirkoBanchi

+0

@caf私は同様の質問がありますが、ブートパラメータを使用してmmap:stackoverflow.com/q/12790382/143897?あなたの発見のいくつかを提供できますか?ありがとう。 –

関連する問題