歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux中mmap系統調用原理分析與實現

 1、mmap系統調用(功能)
      void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )
      內存映射函數mmap, 負責把文件內容映射到進程的虛擬內存空間, 通過對這段內存的讀取和修改,來實現對文件的讀取和修改,而不需要再調用read,write等操作。

2、mmap系統調用(參數)
      1)addr: 指定映射的起始地址, 通常設為NULL, 由系統指定。
      2)length: 映射到內存的文件長度。
      3) prot:   映射區的保護方式, 可以是:
             PROT_EXEC: 映射區可被執行
             PROT_READ: 映射區可被讀取
             PROT_WRITE: 映射區可被寫入

      4)flags: 映射區的特性, 可以是:
            MAP_SHARED:寫入映射區的數據會復制回文件, 且允許其他映射該文件的進程共享。
            MAP_PRIVATE:對映射區的寫入操作會產生一個映射區的復制(copy-on-write), 對此區域所做的修改不會寫回原文件。

      5)fd: 由open返回的文件描述符, 代表要映射的文件。
      6)offset: 以文件開始處的偏移量, 必須是分頁大小的整數倍, 通常為0, 表示從文件頭開始映射。

3、解除映射
      int munmap(void *start,size_t length)
     功能:取消參數start所指向的映射內存,參數length表示欲取消的內存大小。
    返回值:解除成功返回0,否則返回-1,錯誤原因存於errno中。

實例分析
mmap系統調用

4、虛擬內存區域
      虛擬內存區域是進程的虛擬地址空間中的一個同質區間,即具有同樣特性的連續地址范圍。一個進程的內存映象由下面幾部分組成:程序代碼、數據、BSS
和棧區域,以及內存映射的區域。

 一個進程的內存區域可以通過查看:/proc/pid/maps
08048000-0804f000 r-xp 00000000 08:01 573748 /sbin/rpc.statd #text
0804f000-08050000 rw-p 00007000 08:01 573748 /sbin/rpc.statd #data
08050000-08055000 rwxp 00000000 00:00 0 #bss
040000000-40015000 r-xp 00000000 08:01 933965 /lib/ld2.3.2.so #text
40015000-40016000 rw-p 00014000 08:01 933965 /lib/ld-2.3.2.so #data

       每一行的域為:start_end perm offset major:minor inode
       1) Start: 該區域起始虛擬地址
       2) End: 該區域結束虛擬地址
       3) Perm: 讀、寫和執行權限;表示對這個區域,允許進程做什麼。這個域的最後一個字符要麼是p表示私有的,要麼是s表示共享的。
       4) Offset: 被映射部分在文件中的起始地址
       5) Major、minor:主次設備號
       6) Inode:索引結點

5、vm_area_struct
      Linux內核使用結構vm_area_struct(<linux/mm_types.h>)來描述虛擬內存區域,其中幾個主要成員如下:
     1)unsigned long vm_start   虛擬內存區域起始地址
     2)unsigned long vm_end    虛擬內存區域結束地址

     3)unsigned long vm_flags  該區域的標記。如:VM_IO和VM_RESERVED。VM_IO將該VMA標記為內存映射的IO區域,VM_IO會阻止系統將該區域包含在進程的存放轉
存(core dump )中,VM_RESERVED標志內存區域不能被換出。

6、mmap設備操作
      映射一個設備是指把用戶空間的一段地址關聯到設備內存上。當程序讀寫這段用戶空間的地址時,它實際上是在訪問設備。

      mmap設備方法需要完成什麼功能?
      mmap方法是file_oprations結構的成員,在mmap系統調用發出時被調用。在此之前,內核已經完成了很多工作。mmap設備方法所需要做的就是建立
虛擬地址到物理地址的頁表。
      int (*mmap) (struct file *, struct vm_area_struct *)

      mmap如何完成頁表的建立?
     方法有二:
     1)使用remap_pfn_range一次建立所有頁表;
     2)使用nopage VMA方法每次建立一個頁表。

     構造頁表的工作可由remap_pfn_range函數完成,原型如下:
     int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,unsigned long pfn, unsigned long size, pgprot_t prot)

     vma:           虛擬內存區域指針
     virt_addr:   虛擬地址的起始值

     pfn:             要映射的物理地址所在的物理頁幀號,可將物理地址>>PAGE_SHIFT得到。
     size:           要映射的區域的大小。
     prot:            VMA的保護屬性。


int memdev_mmap(struct file*filp, struct vm_area_struct *vma)
{
Vma->vm_flags |= VM_IO;
Vma->vm_flags |= VM_RESERVED;
if (remap_pfn_range(vma, vma->vm_start,
virt_to_phys(dev- >data)>> PAGE_SHIFT,
size,
vma->vm_page_prot))
return -EAGAIN;
return 0;
}

Copyright © Linux教程網 All Rights Reserved