這次我們來講述mmap較爲具體一點的實現細節。
mmap設備方法是file_operations結構的成員,在Mmap系統調用發出時被調用。在此之前,內核已經完成了很多工作。mmap設備方法所需要做的就是建立虛擬地址到物理地址的頁表。
prototype : int (*mmap)(struct file *, struct vm_area_struct *);
parameter: struct file * : 需要操作的文件
struct vm_area_struct * : 內核自動幫我們找到的一個虛擬內存區域。
return : 虛擬內存區域起始地址
Linux內核使用結構vm_area_struct 來描述虛擬虛擬內存區域,其中幾個主要成員如下:
unsigned long vm_start : 虛擬內存區域起始地址
unsinged long vm_end : 虛擬內存區域結束地址
unsigned long vm_flags : 該區域的標記(能否直接把信息通過虛擬地址存入物理地址等)
通過上面的介紹,其實mmap是如何完成頁表的建立呢?
方法有兩種:
1.使用remap_pfn_range一次建立所有頁表
2.使用nopage VMA方法每次建立一個頁表
我們這裏詳細介紹方法一。
prototype : int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn, unsigned long size, pgprot_t prot)
parameter: vma : 虛擬內存區域指針
addr : 虛擬地址的起始值
pfn : 要映射的物理地址的頁幀號,即將物理地址右移PAGE_SHIFT(12位),至於爲什
麼是12位,敬請查看《深入理解LINUX內核》內存管理部分
size : 要映射的區域的大小。
prot : VMA的保護屬性。
return : 返回虛擬內存起始地址。
操作實例:
注意這裏的remap_pfn_range函數裏的virt_to_phys(dev -> data),因爲例子採用的“設備”其實就是內存,所以需要先轉化成物理地址再移位。如果以後我們操作實際的硬件,這裏就不用轉化了,直接填入物理地址即可。