繼 Linux programming 課程紀錄「
|
當 user-space 呼叫 mmap() system call wrapper function 後,kernel 會在 process address space 裡建立新的 VMA,並在 callback mmap driver function 時將「該」VMA 傳遞給我們的驅動程式。
因此,在驅動程式裡,只需要利用 remap_page_range() 將 kernel-space 的 memory:
- I/O memory
- RAM(reserved pages)
- Virtual address space(reserved pages)
對應到該 VMA 即可。最後,寫出了以下的 skeleton code:
// refer to: bttv-dirver.c int do_card_mmap(struct vm_area_struct *vma, char *adr, unsigned long size) { unsigned long start = (unsigned long)adr; unsigned long page, pos; pos = (unsigned long)BaseIOAddress; #if 1 // page or the total size ? while (size >0) { page = pos; if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start+=PAGE_SIZE; pos+=PAGE_SIZE; size-=PAGE_SIZE; } #else if (remap_page_range(vma, start, pos, size, PAGE_SHARED)) return -EAGAIN; #endif return 0; } // refer to: videodev.c int card_mmap(struct file *filp, struct vm_area_struct *vma) { do_card_mmap(vma, (char *)vma->vm_start, (unsigned long)(vma->vm_end-vma->vm_start)); return 0; } /**************************************************/ struct file_operations card_fops = { open:card_open, release:card_release, ioctl:card_ioctl, mmap:card_mmap, };
remap_page_range() 的原理是去修改 page table,但是要不要以 "page" 為最小單位做 page table 的修改(呼叫 'remap_page_range'),必須視情況而定!