mmap概述

mmap/munmap接口是用戶空間的最經常使用的一個系統調用接口,不管是在用戶程序中分配內存、讀寫大文件,連接動態庫文件,仍是多進程間共享內存,均可以看到mmap/munmap的身影。mmap/munmap函數聲明以下:數組

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
  • addr:用於指定映射到進程空間的起始地址,爲了應用程序的可移植性,通常設置爲NULL,讓內核來選擇一個合適的地址。
  • length:表示映射到進程地址空間的大小
  • prot:用於設置內核映射區域的讀寫屬性等。
  • flags:用於設置內存映射的屬性,例如共享映射、私有映射等。
  • fd:表示這個是一個文件映射,fd是打開文件的句柄。
  • offset:在文件映射時,表示文件的偏移量。

prot參數一般表示映射頁面的的讀寫權限,能夠有以下參數組合:函數

  • PROT_EXEC:表示映射的頁面是能夠執行的。
  • PROT_READ:表示映射的頁面是能夠讀取的。
  • PROT_WRITE:表示映射的頁面是能夠寫入的。
  • PROT_NONE:表示映射的頁面是不可訪問的。

flags參數也是一個重要的參數,有以下常見的參數:code

  • MAP_SHARED:建立一個共享映射的區域。多個進程能夠經過共享映射方式來映射一個文件,這樣其餘進程也能夠看到映射內容的改變,修改後的內容會同步到磁盤文件中。
  • MAP_PRIVATE:建立一個私有的寫時複製的映射。多個進程能夠經過私有映射的方式來映射一個文件,這樣其餘進程不會看到映射內容的改變,修改後的內容也不會同步到磁盤文件中。
  • MAP_ANONYMOUS:建立一個匿名映射,即沒有關聯到文件的映射。
  • MAP_FIXED:使用參數addr建立映射,若是內核沒法映射指定地址addr,那麼mmap會返回失敗,參數addr要求按頁對齊。若是addr和length指定的進程地址空間和已有的VMA區域重疊,那麼內核會調用do_munmap()函數把這段重疊區域銷燬,而後從新映射新的內容。
  • MAP_POPULATE:對於文件映射來講,會提早預讀文件內容到映射區域,該特性只支持私用映射。

參數fd能夠看出mmap映射是否和文件相關聯,所以Linux內核中映射能夠分爲匿名映射和文件映射。接口

  • 匿名映射:沒有映射對應的相關文件,這種映射的內存區域的內容會被初始化爲0。
  • 文件映射:映射和實際文件相關聯,一般是把文件的內容映射到進程地址空間,這樣應用程序就能夠像操做進程地址空間同樣讀寫文件。

最後根據文件關聯性和映射區域是否共享等屬性,又能夠分爲以下4種,見表2.1。進程

​ mmap映射類型內存

映射類型 映射類型
私有映射 共享映射
匿名映射 私有匿名映射-一般用於內存分配 共享匿名映射-一般用於進程間共享內存
文件映射 私有文件映射-一般用於加載動態庫 共享文件映射-一般用於內存映射IO,進程間通訊
  1. 私有匿名映射

當使用參數fd=-1且flags=MAP_ANONYMOUS | MAP_PRIVATE時,建立的mmap映射是私有匿名映射。私有匿名映射最多見的用途是在glibc分配大塊內存中,當須要的分配的內存大於MMAP_THREASHOLD(128KB)時,glibc會默認使用mmap代替brk來分配內存。同步

  1. 共享匿名映射

當使用參數fd=-1且flags=MAP_ANONYMOUS | MAP_SHARED。在這種狀況下,建立共享匿名映射。共享匿名映射讓相關進程共享一塊內存區域,一般用於父子進程的之間通訊。it

建立共享匿名映射有以下兩種方式:table

(1)fd=-1且flags= MAP_ANONYMOUS|MAP_SHARED。在這種狀況下,do_mmap_pgoff()->mmap()函數最終調用shmem_zero_setup()來打開一個"/dev/zero"特殊的設備文件。多進程

(2)另一個是直接打開"/dev/zero"設備文件,而後使用這個文件句柄來建立mmap。

  1. 私有文件映射

私有文件映射時flags的標誌位被設置爲MAP_PRIVATE,那麼就會建立私有文件映射。

私有文件映射的最經常使用的場景是加載動態共享庫。

  1. 共享文件映射

建立文件映射時flags的標誌位被設置爲MAP_SHARED,那麼就會建立共享文件映射。若是prot參數指定了PROT_WRITE,那麼打開文件須要制定O_RDWR標誌位。共享文件映射一般有以下場景:

(1)讀寫文件:

把文件內容映射到進程地址空間,同時對映射的內容作了修改,內核的回寫機制(writeback)最終會把修改的內容同步到磁盤中。

(2)進程間通訊:

進程之間的進程地址空間相互隔離,一個進程不能訪問到另一個進程的地址空間。若是多個進程都同時映射到一個相同的文件,就實現了多進程間的共享內存的通訊。若是一個進程對映射內容作了修改,那麼另外的進程是能夠看到的。

相關文章
相關標籤/搜索