mmap 函數(shù):原理與使用(含代碼)

參考

中文資料
英文資料
使用場景

介紹

除了標(biāo)準(zhǔn)的文件 IO枢舶,例如 open, read, write,內(nèi)核還提供接口允許應(yīng)用將文件 map 到內(nèi)存替久。使得內(nèi)存中的一個字節(jié)與文件中的一個字節(jié)一一對應(yīng)凉泄。

  • 優(yōu)勢
    • 讀寫文件避免了 read()write() 系統(tǒng)調(diào)用,也避免了數(shù)據(jù)的拷貝蚯根。
    • 除了潛在的頁錯誤后众,讀寫 map 后的文件不引起系統(tǒng)調(diào)用或者上下文切換。就像訪問內(nèi)存一樣簡單。
    • 多個進(jìn)程 map 同一個對象蒂誉,可以共享數(shù)據(jù)教藻。
    • 可以直接使用指針來跳轉(zhuǎn)到文件某個位置,不必使用 lseek() 系統(tǒng)調(diào)用右锨。
  • 劣勢
    • 內(nèi)存浪費括堤。由于必須要使用整數(shù)頁的內(nèi)存。
    • 導(dǎo)致難以找到連續(xù)的內(nèi)存區(qū)域
    • 創(chuàng)建和維護(hù)映射和相關(guān)的數(shù)據(jù)結(jié)構(gòu)的額外開銷绍移。在大文件和頻繁訪問的文件中痊臭,這個開銷相比 read write 的 copy 開銷小。
mmap 原理

使用方法

函數(shù)原型為:

#include <sys/mman.h>

void * mmap (void *addr,
             size_t len,
             int prot,
             int flags,
             int fd,
             off_t offset);
  • addr
    這個參數(shù)是建議地址(hint)登夫,沒有特別需求一般設(shè)為0。這個函數(shù)會返回一個實際 map 的地址允趟。

  • len
    文件長度恼策。

  • prot
    表明對這塊內(nèi)存的保護(hù)方式,不可與文件訪問方式?jīng)_突潮剪。
    PROT_NONE
    無權(quán)限涣楷,基本沒有用
    PROT_READ
    讀權(quán)限
    PROT_WRITE
    寫權(quán)限
    PROT_EXEC
    執(zhí)行權(quán)限

  • flags
    描述了映射的類型。
    MAP_FIXED
    開啟這個選項抗碰,則 addr 參數(shù)指定的地址是作為必須而不是建議狮斗。如果由于空間不足等問題無法映射則調(diào)用失敗。不建議使用弧蝇。
    MAP_PRIVATE
    表明這個映射不是共享的碳褒。文件使用 copy on write 機(jī)制映射,任何內(nèi)存中的改動并不反映到文件之中看疗。也不反映到其他映射了這個文件的進(jìn)程之中沙峻。如果只需要讀取某個文件而不改變文件內(nèi)容,可以使用這種模式两芳。
    MAP_SHARED
    和其他進(jìn)程共享這個文件摔寨。往內(nèi)存中寫入相當(dāng)于往文件中寫入。會影響映射了這個文件的其他進(jìn)程怖辆。與 MAP_PRIVATE沖突是复。

  • fd
    文件描述符。進(jìn)行 map 之后竖螃,文件的引用計數(shù)會增加淑廊。因此,我們可以在 map 結(jié)束后關(guān)閉 fd斑鼻,進(jìn)程仍然可以訪問它蒋纬。當(dāng)我們 unmap 或者結(jié)束進(jìn)程,引用計數(shù)會減少。

  • offset
    文件偏移蜀备,從文件起始算起关摇。

如果失敗,mmap 函數(shù)將返回 MAP_FAILED碾阁。

頁面對齊

內(nèi)存擁有獨立權(quán)限的最小單位就是頁输虱。因此,mmap 的最小單位也是頁脂凶。addroffset 參數(shù)都必須頁對齊宪睹,len 會被 roundup。被 roundup 的多余的內(nèi)存會以 \0 填充蚕钦。對這一部分的寫入操作不會影響文件亭病。我們可以通過如下方式獲取本機(jī)的頁面大小:

#include <unistd.h>

long page_size = sysconf(_SC_PAGESIZE);

代碼實現(xiàn)

因為項目需求并發(fā)寫入嘶居,為了提高性能罪帖,實現(xiàn)了一個可以并行寫入的mmap。
具體代碼可以查看我的Github邮屁。

遇到的問題

  1. 寫入時發(fā)生錯誤
bus error(core dump)

stackoverflow 大佬的原話:

You are creating a new zero sized file, you can't extend the file size with mmap. You'll get a bus error when you try to write outside the content of the file.

因此使用 lseek 先把文件擴(kuò)展到需要的大小整袁。

  // solve the bus error problem:
  // we should allocate space for the file first.
  lseek(fd, size_lim_-1, SEEK_SET);
  write(fd,"",1);
  1. 文件權(quán)限設(shè)置
int fd = open(file_path_.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);

打開的時候忘了加 0644 設(shè)置權(quán)限。

  1. 文件大小

由于文件最初利用 lseek 擴(kuò)張了一次佑吝,中間有大量的'\0'段坐昙。導(dǎo)致文件在驗證中出錯弹渔,而且打開緩慢畏鼓。

// resize the file to actual size
truncate(file_path_.c_str(), cur_pos_.load());

在析構(gòu)函數(shù)中增加 truncate 解決纠脾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末理郑,一起剝皮案震驚了整個濱河市哩盲,隨后出現(xiàn)的幾起案子挨摸,更是在濱河造成了極大的恐慌镇饮,老刑警劉巖广鳍,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逆趣,死亡現(xiàn)場離奇詭異蝶溶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)宣渗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門抖所,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痕囱,你說我怎么就攤上這事田轧。” “怎么了鞍恢?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵傻粘,是天一觀的道長每窖。 經(jīng)常有香客問我,道長弦悉,這世上最難降的妖魔是什么窒典? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮稽莉,結(jié)果婚禮上瀑志,老公的妹妹穿的比我還像新娘。我一直安慰自己污秆,他們只是感情好劈猪,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著良拼,像睡著了一般战得。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庸推,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天贡避,我揣著相機(jī)與錄音,去河邊找鬼予弧。 笑死,一個胖子當(dāng)著我的面吹牛湖饱,可吹牛的內(nèi)容都是我干的掖蛤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼井厌,長吁一口氣:“原來是場噩夢啊……” “哼蚓庭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仅仆,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤器赞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后墓拜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體港柜,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年咳榜,在試婚紗的時候發(fā)現(xiàn)自己被綠了夏醉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡涌韩,死狀恐怖畔柔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臣樱,我是刑警寧澤靶擦,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布腮考,位于F島的核電站,受9級特大地震影響玄捕,放射性物質(zhì)發(fā)生泄漏踩蔚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一桩盲、第九天 我趴在偏房一處隱蔽的房頂上張望寂纪。 院中可真熱鬧,春花似錦赌结、人聲如沸捞蛋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拟杉。三九已至,卻和暖如春量承,著一層夾襖步出監(jiān)牢的瞬間搬设,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工撕捍, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留拿穴,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓忧风,卻偏偏與公主長得像默色,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子狮腿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • UNIX網(wǎng)絡(luò)編程第二卷進(jìn)程間通信對mmap函數(shù)進(jìn)行了說明腿宰。該函數(shù)主要用途有三個:1、將一個普通文件映射到內(nèi)存中缘厢,通...
    宇文黎琴閱讀 3,502評論 0 4
  • 如果你看完書中的所有例子吃度,你很可能已經(jīng)做完你的實驗和在已經(jīng)越獄的iPhone上的研究。因為和許多人一樣贴硫,幾乎所有的...
    fishmai0閱讀 15,994評論 2 42
  • 轉(zhuǎn)自認(rèn)真分析mmap:是什么 為什么 怎么用 閱讀目錄mmap基礎(chǔ)概念mmap內(nèi)存映射原理mmap和常規(guī)文件操作的...
    扎Zn了老Fe閱讀 840評論 0 3
  • 子曰:“君子不器椿每。” 譯文:孔子說:“君子不像器皿一般(只有一定的用途英遭。)” 不器就是不成為某一個定型的人才拖刃。不被...
    甜_sweet閱讀 171評論 0 1