MemoryMap

在涉及到IO的開(kāi)發(fā)中勾习,我們經(jīng)城缮簦看到零拷貝(zero copy)、內(nèi)存映射(memroy map, 以下簡(jiǎn)稱(chēng)mmap)等技術(shù)被用于提高IO效率英岭,本文將介紹這兩種技術(shù)的基本原理眼滤,說(shuō)明它們是如何提高IO效率的诅需。

相關(guān)概念

Zero copy和mmap涉及到操作系統(tǒng)中的一些基本概念荧库,在了解它們的工作機(jī)制前分衫,我們先來(lái)復(fù)習(xí)一下這些概念。

虛擬內(nèi)存(virtual memory space)

進(jìn)程對(duì)內(nèi)存的讀寫(xiě)不是直接使用物理內(nèi)存地址牵现,而是基于虛擬地址瞎疼。

每個(gè)進(jìn)程運(yùn)行時(shí)壁畸,操作系統(tǒng)都會(huì)為其創(chuàng)建一個(gè)私有的虛擬內(nèi)存捏萍,存放進(jìn)程運(yùn)行時(shí)代碼和數(shù)據(jù)。虛擬內(nèi)存大小取決與操作系統(tǒng)和所在機(jī)器的體系結(jié)構(gòu)走敌,對(duì)于32機(jī)器來(lái)說(shuō)逗噩,空間大小為4g给赞。

操作系統(tǒng)通過(guò)內(nèi)存管理機(jī)制,將虛擬內(nèi)存映射到物理內(nèi)存残邀。

虛擬內(nèi)存使得操作系統(tǒng)可以同時(shí)支持多個(gè)運(yùn)行進(jìn)程安全共享物理內(nèi)存,防止進(jìn)程之間的不安全讀寫(xiě)驱闷。

User space vs kernel space

虛擬內(nèi)存分為兩部分:用戶(hù)空間和內(nèi)核空間空另。用戶(hù)空間存放用戶(hù)代碼和用戶(hù)數(shù)據(jù)蹋砚;內(nèi)核空間存放操作系統(tǒng)代碼。

前面說(shuō)過(guò)循榆,每個(gè)進(jìn)程有自己私有的虛擬內(nèi)存秧饮,不同進(jìn)程的虛擬內(nèi)存中的相同的地址泽篮,被映射到物理內(nèi)存中的不同位置帽撑。但是內(nèi)核空間是個(gè)例外,所有進(jìn)程是共享內(nèi)核空間的历恐,也就是對(duì)不同進(jìn)程來(lái)說(shuō)弱贼,它們內(nèi)核空間內(nèi)的內(nèi)容磷蛹、地址映射實(shí)際上都是相同的践图。

缺頁(yè)中斷(page fault)

操作系統(tǒng)為每個(gè)進(jìn)程的虛擬內(nèi)存和物理內(nèi)存之間建立了一張映射表蒸辆,需要注意的是峭状,虛擬內(nèi)存中的內(nèi)容只會(huì)一部分被裝載到物理內(nèi)存中。

當(dāng)進(jìn)程訪(fǎng)問(wèn)的虛擬地址對(duì)應(yīng)的內(nèi)容不在物理內(nèi)存時(shí)馆铁,操作系統(tǒng)會(huì)觸發(fā)一個(gè)缺頁(yè)中斷莱睁,將物理內(nèi)存中不用的內(nèi)容暫時(shí)置換到磁盤(pán)嘿期,將需要的內(nèi)容讀取道物理內(nèi)存掂铐。通過(guò)這種管理模式罕拂,我們可以在同時(shí)運(yùn)行多個(gè)進(jìn)程的情況下揍异,讓每個(gè)進(jìn)程覺(jué)得自己在獨(dú)享整個(gè)內(nèi)存空間。

User mode vs kernel mode

操作系統(tǒng)至少為進(jìn)程提供兩種運(yùn)行模式:用戶(hù)態(tài)(usermode)衷掷、內(nèi)核態(tài)(kernel mode)。不同的模式柿菩,實(shí)際對(duì)應(yīng)著不同的運(yùn)行權(quán)限戚嗅。

用戶(hù)態(tài)的進(jìn)程,只能訪(fǎng)問(wèn)用戶(hù)空間枢舶,不能直接訪(fǎng)問(wèn)設(shè)備懦胞。而內(nèi)核態(tài)的進(jìn)程,可以訪(fǎng)問(wèn)用戶(hù)空間和內(nèi)核空間祟辟,可以訪(fǎng)問(wèn)硬件設(shè)備医瘫。

進(jìn)程模式切換

一個(gè)進(jìn)程可以通過(guò)系統(tǒng)調(diào)用在用戶(hù)態(tài)和內(nèi)核態(tài)之間切換,此外旧困,中斷、異常等機(jī)制也可以讓進(jìn)程沖用戶(hù)態(tài)切換到內(nèi)核態(tài)稼锅。

這里簡(jiǎn)單說(shuō)明下系統(tǒng)調(diào)用的過(guò)程吼具;

  1. 用戶(hù)態(tài)進(jìn)程準(zhǔn)備好系統(tǒng)調(diào)用的參數(shù);
  2. 進(jìn)程執(zhí)行trap指令
  3. cpu自動(dòng)切換到內(nèi)核態(tài)
  4. cpu讀取進(jìn)程事先設(shè)置的系統(tǒng)調(diào)用參數(shù)
  5. 執(zhí)行指定的系統(tǒng)調(diào)用
  6. 結(jié)束后矩距,進(jìn)程重新被設(shè)置為用戶(hù)態(tài)

工作過(guò)程分析

假定我們現(xiàn)在要實(shí)現(xiàn)一個(gè)讀取文件拗盒,在內(nèi)存中處理,然后將其輸出的需求锥债,我們看看在不同的實(shí)現(xiàn)方式中陡蝇,底層究竟是如何工作的。

普通實(shí)現(xiàn)(read + write)

首先哮肚,我們使用常規(guī)的文件io操作實(shí)現(xiàn)需求登夫。

普通IO
  1. 進(jìn)程通過(guò)系統(tǒng)調(diào)用讀取數(shù)據(jù)
  2. 進(jìn)程切換到內(nèi)核態(tài),通知設(shè)備進(jìn)行讀取
  3. 設(shè)備準(zhǔn)備好的數(shù)據(jù)傳送到內(nèi)核空間
  4. 接收到數(shù)據(jù)后允趟,內(nèi)核態(tài)進(jìn)程將數(shù)據(jù)從內(nèi)核空間拷貝到用戶(hù)空間
  5. 進(jìn)程切換回用戶(hù)態(tài)恼策,繼續(xù)執(zhí)行用戶(hù)空間的代碼:處理數(shù)據(jù)
  6. 進(jìn)程通過(guò)系統(tǒng)調(diào)用輸出數(shù)據(jù)到設(shè)備
  7. 進(jìn)程切換到內(nèi)核態(tài),把數(shù)據(jù)從用戶(hù)空間拷貝到內(nèi)核空間潮剪,通知設(shè)備進(jìn)行輸出操作
  8. 設(shè)備完成任務(wù)后涣楷,進(jìn)程再次從內(nèi)核態(tài)切換回用戶(hù)態(tài)

在上面的過(guò)程中,涉及到4次進(jìn)程模式切換抗碰,兩次內(nèi)存拷貝狮斗。這些操作對(duì)性能會(huì)造成一定影響。

sendfile

接下來(lái)弧蝇,我們通過(guò)sendfile調(diào)用碳褒,減少上述過(guò)程中的內(nèi)存拷貝折砸,實(shí)現(xiàn)零拷貝。

zero copy

通過(guò)sendfile骤视,我們看到進(jìn)程模式切換從4次減少到2次鞍爱,拷貝從2次減少到1次。

但是sendfile只能完成文件的拷貝操作专酗,無(wú)法處理文件內(nèi)容睹逃,mmap則可以幫助我們實(shí)現(xiàn)零拷貝下的處理。

mmap

mmap

通過(guò)調(diào)用memory map祷肯,我們讓操作系統(tǒng)把文件的內(nèi)容映射到內(nèi)存沉填,對(duì)內(nèi)存的讀寫(xiě)將關(guān)聯(lián)到對(duì)應(yīng)的文件。而應(yīng)用通過(guò)訪(fǎng)問(wèn)用戶(hù)空間操作這部分內(nèi)存佑笋,避免了內(nèi)存拷貝操作翼闹。

對(duì)于內(nèi)存映射,有些地方容易被誤解蒋纬,這里說(shuō)明一下猎荠。

內(nèi)存映射是文件到內(nèi)存空間的映射

對(duì)于應(yīng)用來(lái)說(shuō),和文件建立映射關(guān)系的是虛擬地址空間蜀备,而不是物理內(nèi)存或者Heap关摇。

當(dāng)我們建立一個(gè)2g大小的映射時(shí),并不是在heap碾阁,更不是在物理內(nèi)存中分配了這么大的空間输虱,僅僅是在虛擬地址空間中劃出了這么大一個(gè)區(qū)域而已。

應(yīng)用訪(fǎng)問(wèn)內(nèi)存映射區(qū)域時(shí)脂凶,操作系統(tǒng)會(huì)把虛擬的地址映射成真正的物理內(nèi)存地址和底層文件的偏移量宪睹。如果應(yīng)用訪(fǎng)問(wèn)的虛擬地址對(duì)應(yīng)的文件內(nèi)容尚未被裝入內(nèi)存,操作系統(tǒng)通過(guò)缺頁(yè)中斷蚕钦,將內(nèi)存中的部分內(nèi)容交換出去亭病,騰出空間將文件的內(nèi)容讀取到內(nèi)存。

內(nèi)存映射對(duì)性能的提升是有條件的

通過(guò)內(nèi)存映射訪(fǎng)問(wèn)文件冠桃,雖然減少了內(nèi)存拷貝命贴,減少了系統(tǒng)調(diào)用引起的進(jìn)程模式切換,但是過(guò)程中需要承擔(dān)缺頁(yè)中斷的負(fù)擔(dān)食听。

對(duì)于小文件的讀取胸蛛,或者對(duì)于append模式的文件讀寫(xiě),內(nèi)存映射的性能未必優(yōu)于普通io操作樱报。只有對(duì)大文件的隨機(jī)訪(fǎng)問(wèn)葬项,內(nèi)存映射才可能有明顯優(yōu)勢(shì),不過(guò)這仍然需要更具體的分析和進(jìn)一步的的benchmark測(cè)試迹蛤。

Reference

User mode and Kernel mode, System calls, I/O, Exceptions

User space and kernel space

It's all about buffers: zero-copy, mmap and Java NIO

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末民珍,一起剝皮案震驚了整個(gè)濱河市襟士,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嚷量,老刑警劉巖陋桂,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝶溶,居然都是意外死亡嗜历,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)抖所,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)梨州,“玉大人,你說(shuō)我怎么就攤上這事田轧”┙常” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵傻粘,是天一觀的道長(zhǎng)每窖。 經(jīng)常有香客問(wèn)我,道長(zhǎng)弦悉,這世上最難降的妖魔是什么岛请? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮警绩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盅称。我一直安慰自己肩祥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布缩膝。 她就那樣靜靜地躺著混狠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疾层。 梳的紋絲不亂的頭發(fā)上将饺,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音痛黎,去河邊找鬼予弧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛湖饱,可吹牛的內(nèi)容都是我干的掖蛤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼井厌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蚓庭!你這毒婦竟也來(lái)了致讥?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤器赞,失蹤者是張志新(化名)和其女友劉穎垢袱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體港柜,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡请契,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了潘懊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姚糊。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖授舟,靈堂內(nèi)的尸體忽然破棺而出救恨,到底是詐尸還是另有隱情,我是刑警寧澤释树,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布肠槽,位于F島的核電站,受9級(jí)特大地震影響奢啥,放射性物質(zhì)發(fā)生泄漏秸仙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一桩盲、第九天 我趴在偏房一處隱蔽的房頂上張望寂纪。 院中可真熱鬧,春花似錦赌结、人聲如沸捞蛋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拟杉。三九已至,卻和暖如春量承,著一層夾襖步出監(jiān)牢的瞬間搬设,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工撕捍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拿穴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓卦洽,卻偏偏與公主長(zhǎng)得像贞言,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阀蒂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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