mmap 共享內存深刻總結

概述

mmap()系統調用在調用進程的虛擬地址空間中建立一個新的內存映射。munmap()系統調用執行逆操做,即從進程的地址空間刪除一個映射。html

映射能夠分爲兩種:基於文件的映射和匿名映射。文件映射將一個文件區域中的內容映射到進程的虛擬地址空間中。匿名映射(經過使用MAP_ANONYMOUS)標記或映射/dev/zero來建立)並無對應的文件區域,該映射中的字節會被初始化爲0。ui

映射既能夠是私有的(MAP_PRIVATE),也能夠是共享的(MAP_SHARED)。這種差異肯定了在共享內存上發生的變動的可見性,對於文件映射來說,這種差異還肯定了內核是否會將映射內容上發生的變動傳遞到底層文件上。當一個進程使用MAP_PAIVATE映射一個文件以後,在映射內容上發生的變動對其餘進程是不可見的,而且也不會反應到映射文件上。MAP_SHARED文件映射的作法則相反——在映射上發生的變動對其餘進程可見而且會反應到映射文件上。.net

儘管內核會自動地將發生在一個MAP_SHARED映射內容上的變動反應到底層文件上(pdflush線程),但它不保證合適完成這個操做。應用程序可使用msync()系統調用來顯示地控制一個映射內容什麼時候與映射文件進行同步。線程

內存映射有多種用途:unix

  1. 分配進程私有的內存(私有匿名映射)
  2. 對一個進程的文本段和初始化數據段中的內容進行初始化(私有文件映射)
  3. 在經過fork()關聯起來的進程之間共享內存(共享匿名映射)
  4. 執行內存映射I/O,還能夠將其與無關簡稱之間的內存共享結合起來(共享文件映射)

在訪問一個映射的內容時可能會遇到兩個信號。若是在訪問映射時違反了映射之上的保護規則(或訪問一個當前未被映射的地址),那麼就會產生一個SIGSEGV信號。對於基於文件的映射來說,若是訪問的映射部分在文件中沒有相關區域與之對應(即映射大於底層文件,但仍算映射了,而不是未映射),那麼就會產生一個SIGBUS信號。htm

交換空間過分利用容許系統給進程分配比實際可用的RAM與交換空間之和更多的內存。過分利用之因此多是由於全部進程都不會所有用完爲其分配的內存。使用MAP_NORESERVE標記能夠控制每一個mmap()調用的過分利用狀況,而是用/proc文件則能夠控制整個系統的過分利用狀況。blog

mremap()系統調用容許調整一個既有映射的大小。remap_file_pages()系統調用容許建立非線性文件映射。進程

對於mmap()映射文件和read()文件來講,read()在讀次數少的狀況下比mmap()快。由於雖然mmap()不須要read()的那一次內存拷貝,可是硬件的發展,使得內存拷貝消耗時間極大下降了。並且mmap()的開銷在於缺頁中斷,處理任務比較多。而且,mmap以後,再有讀操做不會通過系統調用,因此在LRU比較最近使用的頁時並不佔優點,容易被換出內存。因此,普通讀的狀況下(排除反覆讀),read()一般比mmap()來得更快。內存

關於mmap,這裏有一張圖挺有意思的:mmap 文件映射內存詳解 rem

相關文章
相關標籤/搜索