Linux デバイス ドライバーを開発していますが、ユーザーが割り当てたメモリ領域にアクセスする方法を理解する必要があります。詳細には、32 バイトのバッファーの場合、ユーザーは次のように呼び出します。
void *UserAddr;
posix_memalign(&UserAddr, getpagesize(), 32); //allocation of the page-alligned buffer
memset(UserAddr, 0x55, 32); //just to see if the data in the buffer is correct
ioctl(fd, MAP_BUFFER, UserAddr); //call kernel module
ここで、カーネル モジュール ioctl で、DMA 操作のために物理アドレスを pci デバイスに渡す必要があります。私が現在行っていることは次のとおりです(この例は、正しいかどうかを理解するために1ページのみです):
if(!access_ok(VERIFY_READ,(char *)user_address,32*sizeof(u32)))
goto error1;
down_read(¤t->mm->mmap_sem);
if(get_user_pages(current, current->mm,(unsigned long)user_address,1,1,0,pages_list,NULL)<1)
goto error2;
up_read(¤t->mm->mmap_sem);
phys_addr=pci_map_page(dev,pages_list[0],0,PAGE_SIZE,DMA_BIDIRECTIONAL);
コードは正しく動作しますが、私の質問は次のとおりです。
- ページを「固定」しているのは誰ですか? または明示的に SetPageReserved(pages_list[0]) を呼び出す必要がありますか?
- バッファを使い終わったときのリリースはどのように機能しますか? pci_unmap とそれだけですか? SetPageReserved を呼び出しても?
- 一般に、ユーザー空間アドレスで virt_to_phys を呼び出すことは安全ですか (ページが固定されている場合)? (または DMA の場合は virt_to_bus)
- これはユーザー空間バッファにアクセスするための「ベストプラクティス」ですか?