繼 Linux programming 課程紀錄「小談 mmap() 與 VMA」後,今天在 Linux device driver 課程再聊到有關 VMA 與 mmap driver function 的重要觀念;重點紀錄如下。
當 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'),必須視情況而定!
同學對此部份如有觀念上的疑問,可透過 forum 討論。
來源: Jollen's Blog
Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue
您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw