linux drivers中的mmap實(shí)現(xiàn)
drivers中file_operations的mmap操作的作用是:
將設(shè)備驅(qū)動(dòng)內(nèi)核空間的內(nèi)存映射到用戶空間里,可以通過用戶空間中的mmap系統(tǒng)調(diào)用代替系統(tǒng)調(diào)用write和read。目的是提高讀寫效率。
系統(tǒng)調(diào)用mmap:
void* mmap (caddr_t addr, size_t len, int prot, int flags, off_t offset)
其中addr一般為NULL,目的是使內(nèi)核自動(dòng)分配可用的虛擬空間地址,并通過返回值返回,并與MAP_FAILED比較;
prot一般為PROT_WRITE | PROT_READ; flags為MAP_SHARED或MAP_PRIVATE之一;offset表示從設(shè)備文件都開始多大偏移處映射,一般為0。
文件操作mmap :
int (*mmap) (struct file* filp, struct vm_area_struct* vma)
定義struct vm_operations_struct xxx_vm_ops = {
.open = xxx_vm_open,
.close = xxx_vm_close,
.nopage = xxx_vm_nopage,
};
編寫mmap文件操作函數(shù)的方式有兩種:
一.使用remap_pfn_range一次性申請(qǐng),不需要定義nopage函數(shù)
1.在mmap中調(diào)用remap_pfn_range;
2.在mmap中對(duì)vma->vm_ops進(jìn)行附值;
3.在mmap結(jié)尾處主動(dòng)調(diào)用vm_ops中的open;
二.定義nopage函數(shù),在發(fā)生缺頁(yè)時(shí)由內(nèi)核申請(qǐng)內(nèi)存中的物理頁(yè),由driver在nopage中將page與vma掛鉤
1.mmap中除了對(duì)vma->vm_ops進(jìn)行附值和主動(dòng)調(diào)用vm_ops中的open外;
2.將設(shè)備內(nèi)存首先按PAGE_SIZE對(duì)齊,最終只將頁(yè)對(duì)齊的設(shè)備內(nèi)存映射到用戶空間中。然后將對(duì)齊操作處理后的虛擬地址逐頁(yè)進(jìn)行SetPageReserved(virt_to_page(virt_addr))保留(可選)
3.在nopage函數(shù)中,首先計(jì)算缺頁(yè)的虛擬內(nèi)存地址實(shí)際的內(nèi)存頁(yè)物理地址與設(shè)備文件開始處的偏移量offset;然后比較該偏移量是否超過映射的設(shè)備文件大小;最后將該缺頁(yè)地址的虛擬地址變換成頁(yè)幀號(hào)并申請(qǐng)?jiān)擁?yè)。