Linux內(nèi)存映射mmap原理分析

一直都對(duì)內(nèi)存映射文件這個(gè)概念很模糊缺猛,不知道它和虛擬內(nèi)存有什么區(qū)別拷沸,而且映射這個(gè)詞也很讓人迷茫,今天終于搞清楚了消玄。跟伏。丢胚。下面,我先解釋一下我對(duì)映射這個(gè)詞的理解受扳,再區(qū)分一下幾個(gè)容易混淆的概念携龟,之后,什么是內(nèi)存映射就很明朗了勘高。

原理

首先峡蟋,“映射”這個(gè)詞,就和數(shù)學(xué)課上說的“一一映射”是一個(gè)意思华望,就是建立一種一一對(duì)應(yīng)關(guān)系蕊蝗,在這里主要是只?硬盤上文件?的位置與進(jìn)程?邏輯地址空間?中一塊大小相同的區(qū)域之間的一一對(duì)應(yīng),如圖1中過程1所示立美。這種對(duì)應(yīng)關(guān)系純屬是邏輯上的概念匿又,物理上是不存在的,原因是進(jìn)程的邏輯地址空間本身就是不存在的建蹄。在內(nèi)存映射的過程中碌更,并沒有實(shí)際的數(shù)據(jù)拷貝,文件沒有被載入內(nèi)存洞慎,只是邏輯上被放入了內(nèi)存痛单,具體到代碼,就是建立并初始化了相關(guān)的數(shù)據(jù)結(jié)構(gòu)(struct?address_space)劲腿,這個(gè)過程有系統(tǒng)調(diào)用mmap()實(shí)現(xiàn)旭绒,所以建立內(nèi)存映射的效率很高。

既然建立內(nèi)存映射沒有進(jìn)行實(shí)際的數(shù)據(jù)拷貝焦人,那么進(jìn)程又怎么能最終直接通過內(nèi)存操作訪問到硬盤上的文件呢挥吵?那就要看內(nèi)存映射之后的幾個(gè)相關(guān)的過程了。

mmap()會(huì)返回一個(gè)指針ptr花椭,它指向進(jìn)程邏輯地址空間中的一個(gè)地址忽匈,這樣以后,進(jìn)程無需再調(diào)用read或write對(duì)文件進(jìn)行讀寫矿辽,而只需要通過ptr就能夠操作文件丹允。但是ptr所指向的是一個(gè)邏輯地址,要操作其中的數(shù)據(jù)袋倔,必須通過MMU將邏輯地址轉(zhuǎn)換成物理地址雕蔽,如圖1中過程2所示。這個(gè)過程與內(nèi)存映射無關(guān)宾娜。?

前面講過批狐,建立內(nèi)存映射并沒有實(shí)際拷貝數(shù)據(jù),這時(shí)前塔,MMU在地址映射表中是無法找到與ptr相對(duì)應(yīng)的物理地址的贾陷,也就是MMU失敗缘眶,將產(chǎn)生一個(gè)缺頁(yè)中斷,缺頁(yè)中斷的中斷響應(yīng)函數(shù)會(huì)在swap中尋找相對(duì)應(yīng)的頁(yè)面髓废,如果找不到(也就是該文件從來沒有被讀入內(nèi)存的情況),則會(huì)通過mmap()建立的映射關(guān)系该抒,從硬盤上將文件讀取到物理內(nèi)存中慌洪,如圖1中過程3所示。這個(gè)過程與內(nèi)存映射無關(guān)凑保。

如果在拷貝數(shù)據(jù)時(shí)冈爹,發(fā)現(xiàn)物理內(nèi)存不夠用,則會(huì)通過虛擬內(nèi)存機(jī)制(swap)將暫時(shí)不用的物理頁(yè)面交換到硬盤上欧引,如圖1中過程4所示频伤。這個(gè)過程也與內(nèi)存映射無關(guān)。

效率

從代碼層面上看芝此,從硬盤上將文件讀入內(nèi)存憋肖,都要經(jīng)過文件系統(tǒng)進(jìn)行數(shù)據(jù)拷貝,并且數(shù)據(jù)拷貝操作是由文件系統(tǒng)和硬件驅(qū)動(dòng)實(shí)現(xiàn)的婚苹,理論上來說岸更,拷貝數(shù)據(jù)的效率是一樣的。但是通過內(nèi)存映射的方法訪問硬盤上的文件膊升,效率要比read和write系統(tǒng)調(diào)用高怎炊,這是為什么呢?原因是read()是系統(tǒng)調(diào)用廓译,其中進(jìn)行了數(shù)據(jù)拷貝评肆,它首先將文件內(nèi)容從硬盤拷貝到內(nèi)核空間的一個(gè)緩沖區(qū),如圖2中過程1非区,然后再將這些數(shù)據(jù)拷貝到用戶空間瓜挽,如圖2中過程2,在這個(gè)過程中院仿,實(shí)際上完成了?兩次數(shù)據(jù)拷貝?秸抚;

而mmap()也是系統(tǒng)調(diào)用,如前所述歹垫,mmap()中沒有進(jìn)行數(shù)據(jù)拷貝剥汤,真正的數(shù)據(jù)拷貝是在缺頁(yè)中斷處理時(shí)進(jìn)行的,由于mmap()將文件直接映射到用戶空間排惨,所以中斷處理函數(shù)根據(jù)這個(gè)映射關(guān)系吭敢,直接將文件從硬盤拷貝到用戶空間,只進(jìn)行了?一次數(shù)據(jù)拷貝?暮芭。因此鹿驼,內(nèi)存映射的效率要比read/write效率高欲低。


下面這個(gè)程序,通過read和mmap兩種方法分別對(duì)硬盤上一個(gè)名為“mmap_test”的文件進(jìn)行操作畜晰,文件中存有10000個(gè)整數(shù)砾莱,程序兩次使用不同的方法將它們讀出,加1凄鼻,再寫回硬盤腊瑟。通過對(duì)比可以看出,read消耗的時(shí)間將近是mmap的兩到三倍块蚌。

WR?);

if(sizeof(int)*MAX?!=?read(?fd,?(void*)array,sizeof(int)*MAX?)?)

{

printf("Reading?data?failed.../n");

return-1;

}

for(?i=0;?i

++array[?i?];

if(sizeof(int)*MAX?!=?write(?fd,?(void*)array,sizeof(int)*MAX?)?)

{

printf("Writing?data?failed.../n");

return-1;

}

free(array);

close(?fd?);

gettimeofday(?&tv2,NULL);

printf("Time?of?read/write:?%dms/n",?tv2.tv_usec-tv1.tv_usec?);

/*mmap*/

gettimeofday(?&tv1,NULL);

fd?=?open("mmap_test",?O_RDWR?);

array=?mmap(NULL,sizeof(int)*MAX,?PROT_READ|PROT_WRITE,?MAP_SHARED,?fd,0);

for(?i=0;?i

++array[?i?];

munmap(array,sizeof(int)*MAX?);

msync(array,sizeof(int)*MAX,?MS_SYNC?);

free(array);

close(?fd?);

gettimeofday(?&tv2,NULL);

printf("Time?of?mmap:?%dms/n",?tv2.tv_usec-tv1.tv_usec?);

return0;

}

輸出結(jié)果:

Timeofread/write:154ms

Timeofmmap:68ms

V ? ? X ? 獲?取?更 多 精彩 內(nèi)容

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闰非,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子峭范,更是在濱河造成了極大的恐慌财松,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纱控,死亡現(xiàn)場(chǎng)離奇詭異辆毡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)其徙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門胚迫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唾那,你說我怎么就攤上這事访锻。” “怎么了闹获?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵期犬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我避诽,道長(zhǎng)龟虎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任沙庐,我火速辦了婚禮鲤妥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拱雏。我一直安慰自己棉安,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布铸抑。 她就那樣靜靜地躺著贡耽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蒲赂,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天阱冶,我揣著相機(jī)與錄音,去河邊找鬼滥嘴。 笑死木蹬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的若皱。 我是一名探鬼主播届囚,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼是尖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泥耀,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤饺汹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后痰催,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兜辞,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年夸溶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逸吵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缝裁,死狀恐怖扫皱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捷绑,我是刑警寧澤韩脑,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站粹污,受9級(jí)特大地震影響段多,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壮吩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一进苍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸭叙,春花似錦觉啊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春搜吧,著一層夾襖步出監(jiān)牢的瞬間市俊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工滤奈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摆昧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓蜒程,卻偏偏與公主長(zhǎng)得像绅你,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昭躺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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

  • 1. 硬鏈接和軟連接區(qū)別 硬連接-------指通過索引節(jié)點(diǎn)來進(jìn)行連接忌锯。在Linux的文件系統(tǒng)中,保存在磁盤分區(qū)...
    杰倫哎呦哎呦閱讀 2,258評(píng)論 0 2
  • Linux進(jìn)程通信實(shí)現(xiàn)機(jī)制有很多领炫,也有各自優(yōu)缺點(diǎn)和適用場(chǎng)景偶垮,關(guān)于她們之間的對(duì)比,等各種通信機(jī)制一一介紹后帝洪,再來一個(gè)...
    batbattle閱讀 4,075評(píng)論 3 13
  • 轉(zhuǎn)自認(rèn)真分析mmap:是什么 為什么 怎么用 閱讀目錄mmap基礎(chǔ)概念mmap內(nèi)存映射原理mmap和常規(guī)文件操作的...
    扎Zn了老Fe閱讀 840評(píng)論 0 3
  • mmap基礎(chǔ)概念 mmap是一種內(nèi)存映射文件的方法似舵,即將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間,實(shí)現(xiàn)文件磁盤地址...
    神奇的考拉閱讀 2,198評(píng)論 3 6
  • 棧(stack):又稱堆棧脆淹,棧是由編譯器自動(dòng)分配釋放常空,存放函數(shù)的參數(shù)值,局部變量的值等(但不包括static聲明的...
    4b5317535aa5閱讀 1,888評(píng)論 0 2