mmap的使用

mmap 即 memory map奏甫,也就是內存映射尖飞。
mmap操作提供了一種機制症副,讓用戶程序直接訪問設備內存,這種機制葫松,相比較在用戶空間和內核空間互相拷貝數據瓦糕,效率更高底洗。在要求高性能的應用中比較常用腋么。mmap映射內存必須是頁面大小的整數倍,面向流的設備不能進行mmap亥揖,mmap的實現和硬件有關珊擂。

image.png

映射條件:
mmap()必須以PAGE_SIZE為單位進行映射圣勒,而內存也只能以頁為單位進行映射,若要映射非PAGE_SIZE整數倍的地址范圍摧扇,要先進行內存對齊圣贸,強行以PAGE_SIZE的倍數大小進行映射。

頭文件:
<sys/mman.h>

函數原型:
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
int munmap(void* start,size_t length);

參數說明:
start:映射區(qū)的開始地址扛稽,設置為0時表示由系統(tǒng)決定映射區(qū)的起始地址吁峻。
length:映射區(qū)的長度。//長度單位是 以字節(jié)為單位在张,不足一內存頁按一內存頁處理
prot:期望的內存保護標志用含,不能與文件的打開模式沖突。是以下的某個值帮匾,可以通過or運算合理地組合在一起
PROT_EXEC //頁內容可以被執(zhí)行
PROT_READ //頁內容可以被讀取
PROT_WRITE //頁可以被寫入
PROT_NONE //頁不可訪問
flags:指定映射對象的類型啄骇,映射選項和映射頁是否可以共享。它的值可以是一個或者多個以下位的組合體
MAP_FIXED //使用指定的映射起始地址瘟斜,如果由start和len參數指定的內存區(qū)重疊于現存的映射空間缸夹,重疊部分將會被丟棄。如果指定的起始地址不可用螺句,操作將會失敗虽惭。并且起始地址必須落在頁的邊界上。
MAP_SHARED //與其它所有映射這個對象的進程共享映射空間壹蔓。對共享區(qū)的寫入趟妥,相當于輸出到文件。直到msync()或者munmap()被調用佣蓉,文件實際上不會被更新披摄。
MAP_PRIVATE //建立一個寫入時拷貝的私有映射。內存區(qū)域的寫入不會影響到原文件勇凭。這個標志和以上標志是互斥的疚膊,只能使用其中一個。
MAP_DENYWRITE //這個標志被忽略虾标。
MAP_EXECUTABLE //同上
MAP_NORESERVE //不要為這個映射保留交換空間寓盗。當交換空間被保留,對映射區(qū)修改的可能會得到保證璧函。當交換空間不被保留傀蚌,同時內存不足,對映射區(qū)的修改會引起段違例信號蘸吓。
MAP_LOCKED //鎖定映射區(qū)的頁面善炫,從而防止頁面被交換出內存。
MAP_GROWSDOWN //用于堆棧库继,告訴內核VM系統(tǒng)箩艺,映射區(qū)可以向下擴展窜醉。
MAP_ANONYMOUS //匿名映射,映射區(qū)不與任何文件關聯(lián)艺谆。
MAP_ANON //MAP_ANONYMOUS的別稱榨惰,不再被使用。
MAP_FILE //兼容標志静汤,被忽略琅催。
MAP_32BIT //將映射區(qū)放在進程地址空間的低2GB,MAP_FIXED指定時會被忽略虫给。當前這個標志只在x86-64平臺上得到支持恢暖。
MAP_POPULATE //為文件映射通過預讀的方式準備好頁表。隨后對映射區(qū)的訪問不會被頁違例阻塞狰右。
MAP_NONBLOCK //僅和MAP_POPULATE一起使用時才有意義杰捂。不執(zhí)行預讀,只為已存在于內存中的頁面建立頁表入口棋蚌。
fd:有效的文件描述詞嫁佳。一般是由open()函數返回,其值也可以設置為-1谷暮,此時需要指定flags參數中的MAP_ANON,表明進行的是匿名映射蒿往。
offset:被映射對象內容的起點。

返回值
成功執(zhí)行時湿弦,mmap()返回被映射區(qū)的指針瓤漏,munmap()返回0。失敗時颊埃,mmap()返回MAP_FAILED[其值為(void *)-1]蔬充,munmap返回-1。errno被設為以下的某個值
EACCES:訪問出錯
EAGAIN:文件已被鎖定班利,或者太多的內存已被鎖定
EBADF:fd不是有效的文件描述詞
EINVAL:一個或者多個參數無效
ENFILE:已達到系統(tǒng)對打開文件的限制
ENODEV:指定文件所在的文件系統(tǒng)不支持內存映射
ENOMEM:內存不足饥漫,或者進程已超出最大內存映射數量
EPERM:權能不足,操作不允許
ETXTBSY:已寫的方式打開文件罗标,同時指定MAP_DENYWRITE標志
SIGSEGV:試著向只讀區(qū)寫入
SIGBUS:試著訪問不屬于進程的內存區(qū)

特點:

  • mmap 向應用程序提供的內存訪問接口是內存地址連續(xù)的庸队,但是對應的磁盤文件的 page 可以不是地址連續(xù)的闯割;
  • mmap 提供的內存空間是虛擬空間(虛擬內存)彻消,而不是物理空間(物理內存),因此完全可以分配遠遠大于物理內存大小的虛擬空間(例如 16G 內存主機分配 1000G 的 mmap 內存空間)宙拉;
  • mmap 負責映射文件邏輯上一段連續(xù)的數據(物理上可以不連續(xù)存儲)映射為連續(xù)內存宾尚,而這里的文件可以是磁盤文件、驅動假造出的文件(例如 DMA 技術)以及設備鼓黔;
  • mmap 由操作系統(tǒng)負責管理央勒,對同一個文件地址的映射將被所有線程共享,操作系統(tǒng)確保線程安全以及線程可見性澳化;
  • 速度快崔步,mmap 被認為快的原因是因為建立了page到用戶進程的虛地址空間映射,以讀取文件為例缎谷,避免了page從內核空間拷貝到用戶空間井濒。
  • 節(jié)約內存,由于用戶空間與內核空間實際上共用同一份數據列林,因此在大文件場景下在實際物理內存占用上有優(yōu)勢瑞你。

使用說明:

  • 最終被映射文件(即參數的fd)的內容的長度不會超過文件本身的初始大小,即映射不能改變文件的大邢3铡者甲;
  • 在linux中,內存的保護是以頁為基本單位的砌创,即使被映射文件只有一個字節(jié)大小虏缸,內核也會為映射分配一個頁面大小的內存。當被映射文件小于一個頁面大小時嫩实,進程可以對從mmap()返回地址開始的一個頁面大小進行訪問刽辙,而不會出錯;但是甲献,如果對一個頁面以外的地址空間進行訪問宰缤,則導致錯誤發(fā)生。因此晃洒,可用于進程間通信的有效地址空間大小不會超過文件大小及一個頁面大小的和慨灭。
  • 文件一旦被映射后,調用mmap()的進程對返回地址的訪問是對某一內存區(qū)域的訪問球及,暫時脫離了磁盤上文件的影響缘挑。所有對mmap()返回地址空間的操作只在內存中有意義,只有在調用了munmap()后或者msync()時桶略,才把內存中的相應內容寫回磁盤文件语淘,所寫內容仍然不能超過文件的大小。
  • 可以用于進程通信的有效地址空間大小大體上受限于被映射文件的大小际歼,但不完全受限于文件大小惶翻。假設有兩個進程a和b,a用mmap映射了文件file_test鹅心。在進程a執(zhí)行munmap前吕粗,b也內存映射file_test,有效地址空間大小為a映射的length旭愧,否則受限于文件大小颅筋。

適用場景:
mmap 的適用場景實際上非常受限宙暇,在如下場合下可以選擇使用 mmap 機制:

  • 多個線程以只讀的方式同時訪問一個文件,這是因為 mmap 機制下多線程共享了同一物理內存空間议泵,因此節(jié)約了內存占贫。
  • mmap 非常適合用于進程間通信,這是因為對同一文件對應的 mmap 分配的物理內存天然多線程共享先口,并可以依賴于操作系統(tǒng)的同步原語型奥。例如多個進程可能依賴于同一個動態(tài)鏈接庫,利用 mmap 可以實現內存僅僅加載一份動態(tài)鏈接庫碉京,多個進程共享此動態(tài)鏈接庫厢汹。
  • mmap 雖然比 sendfile 等機制多了一次 CPU 全程參與的內存拷貝,但是用戶空間與內核空間并不需要數據拷貝谐宙,因此在正確使用情況下并不比 sendfile 效率差烫葬。

其他注意項:

  • 基于缺頁異常的懶加載
    出于節(jié)約物理內存以及 mmap 方法快速返回的目的,mmap 映射采用懶加載機制凡蜻。具體來說厘灼,通過 mmap 申請 1000G 內存可能僅僅占用了 100MB 的虛擬內存空間,甚至沒有分配實際的物理內存空間咽瓷。當你訪問相關內存地址時设凹,才會進行真正的 write、read 等系統(tǒng)調用茅姜。CPU 會通過陷入缺頁異常的方式來將磁盤上的數據加載到物理內存中闪朱,此時才會發(fā)生真正的物理內存分配。

  • 數據一致性由 OS 確保
    當發(fā)生數據修改時钻洒,內存出現臟頁奋姿,與磁盤文件出現不一致。mmap 機制下由操作系統(tǒng)自動完成內存數據落盤(臟頁回刷)素标,用戶進程通常并不需要手動管理數據落盤称诗。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市头遭,隨后出現的幾起案子寓免,更是在濱河造成了極大的恐慌,老刑警劉巖计维,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袜香,死亡現場離奇詭異,居然都是意外死亡鲫惶,警方通過查閱死者的電腦和手機蜈首,發(fā)現死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人欢策,你說我怎么就攤上這事吆寨。” “怎么了踩寇?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵啄清,是天一觀的道長。 經常有香客問我姑荷,道長,這世上最難降的妖魔是什么缩擂? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任鼠冕,我火速辦了婚禮,結果婚禮上胯盯,老公的妹妹穿的比我還像新娘懈费。我一直安慰自己,他們只是感情好博脑,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布憎乙。 她就那樣靜靜地躺著,像睡著了一般叉趣。 火紅的嫁衣襯著肌膚如雪泞边。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天疗杉,我揣著相機與錄音阵谚,去河邊找鬼。 笑死烟具,一個胖子當著我的面吹牛梢什,可吹牛的內容都是我干的。 我是一名探鬼主播朝聋,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼嗡午,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了冀痕?” 一聲冷哼從身側響起荔睹,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎言蛇,沒想到半個月后应媚,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡猜极,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年中姜,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡丢胚,死狀恐怖翩瓜,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情携龟,我是刑警寧澤兔跌,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站峡蟋,受9級特大地震影響坟桅,放射性物質發(fā)生泄漏。R本人自食惡果不足惜蕊蝗,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一仅乓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蓬戚,春花似錦夸楣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至幢泼,卻和暖如春紧显,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缕棵。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工鸟妙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挥吵。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓重父,卻偏偏與公主長得像,于是被迫代替她去往敵國和親忽匈。 傳聞我的和親對象是個殘疾皇子房午,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容

  • UNIX網絡編程第二卷進程間通信對mmap函數進行了說明。該函數主要用途有三個:1丹允、將一個普通文件映射到內存中郭厌,通...
    宇文黎琴閱讀 3,516評論 0 4
  • linux庫函數mmap()原理 目錄 1.mmap基本概念 2.mmap內存映射原理 3.mmap和常規(guī)文件操作...
    小烏龜爸閱讀 926評論 0 3
  • mmap,munmap-將文件或設備映射(消取映射)到內存 mmap() mmap()將在調用者進程的虛擬地址空間...
    蟹蟹寧閱讀 3,908評論 0 1
  • mmap基礎概念 mmap是一種內存映射文件的方法雕蔽,即將一個文件或者其它對象映射到進程的地址空間折柠,實現了文件磁盤地...
    JamFF閱讀 2,447評論 1 12
  • mmap基礎概念 mmap是一種內存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間批狐,實現文件磁盤地址...
    神奇的考拉閱讀 2,200評論 3 6