[轉載]linux內存映射mmap原理分析

轉自:http://blog.csdn.net/yusiguyuan/article/details/23388771

?

內存映射,簡而言之就是將用戶空間的一段內存區域映射到內核空間,映射成功后,用戶對這段內存區域的修改可以直接反映到內核空間,同樣,內核空間對這段區域的修改也直接反映用戶空間。那么對于內核空間<---->用戶空間兩者之間需要大量數據傳輸等操作的話效率是非常高的。

以下是一個把普遍文件映射到用戶空間的內存區域的示意圖。
圖一:
二、基本函數
? ??mmap函數是unix/linux下的系統調用,詳細內容可參考《Unix Netword programming》卷二12.2節。
mmap系統調用并不是完全為了用于共享內存而設計的。它本身提供了不同于一般對普通文件的訪問方式,進程可以像讀寫內存一樣對普通文件的操作。而Posix或系統V的共享內存IPC則純粹用于共享目的,當然mmap()實現共享內存也是其主要應用之一。
? ? ? ? ??mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間后,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。mmap并不分配空間, 只是將文件映射到調用進程的地址空間里(但是會占掉你的 virutal memory), 然后你就可以用memcpy等操作寫文件, 而不用write()了.寫完后,內存中的內容并不會立即更新到文件中,而是有一段時間的延遲,你可以調用msync()來顯式同步一下, 這樣你所寫的內容就能立即保存到文件里了.這點應該和驅動相關。 不過通過mmap來寫文件這種方式沒辦法增加文件的長度, 因為要映射的長度在調用mmap()的時候就決定了.如果想取消內存映射,可以調用munmap()來取消內存映射
void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)

mmap用于把文件映射到內存空間中,簡單說mmap就是把一個文件的內容在內存里面做一個映像。映射成功后,用戶對這段內存區域的修改可以直接反映到內核空間,同樣,內核空間對這段區域的修改也直接反映用戶空間。那么對于內核空間<---->用戶空間兩者之間需要大量數據傳輸等操作的話效率是非常高的。

?

?

原理

首先,“映射”這個詞,就和數學課上說的“一一映射”是一個意思,就是建立一種一一對應關系,在這里主要是只?硬盤上文件?的位置與進程?邏輯地址空間?中一塊大小相同的區域之間的一一對應,如圖1中過程1所示。這種對應關系純屬是邏輯上的概念,物理上是不存在的,原因是進程的邏輯地址空間本身就是不存在的。在內存映射的過程中,并沒有實際的數據拷貝,文件沒有被載入內存,只是邏輯上被放入了內存,具體到代碼,就是建立并初始化了相關的數據結構(struct?address_space),這個過程有系統調用mmap()實現,所以建立內存映射的效率很高。

?

圖1.內存映射原理??

?

?

?

?

既然建立內存映射沒有進行實際的數據拷貝,那么進程又怎么能最終直接通過內存操作訪問到硬盤上的文件呢?那就要看內存映射之后的幾個相關的過程了。

?

mmap()會返回一個指針ptr,它指向進程邏輯地址空間中的一個地址,這樣以后,進程無需再調用read或write對文件進行讀寫,而只需要通過ptr就能夠操作文件。但是ptr所指向的是一個邏輯地址,要操作其中的數據,必須通過MMU將邏輯地址轉換成物理地址,如圖1中過程2所示。這個過程與內存映射無關。

?

前面講過,建立內存映射并沒有實際拷貝數據,這時,MMU在地址映射表中是無法找到與ptr相對應的物理地址的,也就是MMU失敗,將產生一個缺頁中斷,缺頁中斷的中斷響應函數會在swap中尋找相對應的頁面,如果找不到(也就是該文件從來沒有被讀入內存的情況),則會通過mmap()建立的映射關系,從硬盤上將文件讀取到物理內存中,如圖1中過程3所示。這個過程與內存映射無關。

?

如果在拷貝數據時,發現物理內存不夠用,則會通過虛擬內存機制(swap)將暫時不用的物理頁面交換到硬盤上,如圖1中過程4所示。這個過程也與內存映射無關。

?

?

效率

?

從代碼層面上看,從硬盤上將文件讀入內存,都要經過文件系統進行數據拷貝,并且數據拷貝操作是由文件系統和硬件驅動實現的,理論上來說,拷貝數據的效率是一樣的。但是通過內存映射的方法訪問硬盤上的文件,效率要比read和write系統調用高,這是為什么呢?原因是read()是系統調用,其中進行了數據拷貝,它首先將文件內容從硬盤拷貝到內核空間的一個緩沖區,如圖2中過程1,然后再將這些數據拷貝到用戶空間,如圖2中過程2,在這個過程中,實際上完成了?兩次數據拷貝?;而mmap()也是系統調用,如前所述,mmap()中沒有進行數據拷貝,真正的數據拷貝是在缺頁中斷處理時進行的,由于mmap()將文件直接映射到用戶空間,所以中斷處理函數根據這個映射關系,直接將文件從硬盤拷貝到用戶空間,只進行了?一次數據拷貝?。因此,內存映射的效率要比read/write效率高。

?

?

圖2.read系統調用原理

?

下面這個程序,通過read和mmap兩種方法分別對硬盤上一個名為“mmap_test”的文件進行操作,文件中存有10000個整數,程序兩次使用不同的方法將它們讀出,加1,再寫回硬盤。通過對比可以看出,read消耗的時間將近是mmap的兩到三倍。

?

  1 #include<unistd.h>
  2 
  3 #include<stdio.h>
  4 
  5 #include<stdlib.h>
  6 
  7 #include<string.h>
  8 
  9 #include<sys/types.h>
 10 
 11 #include<sys/stat.h>
 12 
 13 #include<sys/time.h>
 14 
 15 #include<fcntl.h>
 16 
 17 #include<sys/mman.h>
 18 
 19  
 20 
 21 #define MAX 10000
 22 
 23  
 24 
 25 int main()
 26 
 27 {
 28 
 29 int i=0;
 30 
 31 int count=0, fd=0;
 32 
 33 struct timeval tv1, tv2;
 34 
 35 int *array = (int *)malloc( sizeof(int)*MAX );
 36 
 37  
 38 
 39 /*read*/
 40 
 41  
 42 
 43 gettimeofday( &tv1, NULL );
 44 
 45 fd = open( "mmap_test", O_RDWR );
 46 
 47 if( sizeof(int)*MAX != read( fd, (void *)array, sizeof(int)*MAX ) )
 48 
 49 {
 50 
 51 printf( "Reading data failed.../n" );
 52 
 53 return -1;
 54 
 55 }
 56 
 57 for( i=0; i<MAX; ++i )
 58 
 59  
 60 
 61 ++array[ i ];
 62 
 63 if( sizeof(int)*MAX != write( fd, (void *)array, sizeof(int)*MAX ) )
 64 
 65 {
 66 
 67 printf( "Writing data failed.../n" );
 68 
 69 return -1;
 70 
 71 }
 72 
 73 free( array );
 74 
 75 close( fd );
 76 
 77 gettimeofday( &tv2, NULL );
 78 
 79 printf( "Time of read/write: %dms/n", tv2.tv_usec-tv1.tv_usec );
 80 
 81  
 82 
 83 /*mmap*/
 84 
 85  
 86 
 87 gettimeofday( &tv1, NULL );
 88 
 89 fd = open( "mmap_test", O_RDWR );
 90 
 91 array = mmap( NULL, sizeof(int)*MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
 92 
 93 for( i=0; i<MAX; ++i )
 94 
 95  
 96 
 97 ++array[ i ];
 98 
 99 munmap( array, sizeof(int)*MAX );
100 
101 msync( array, sizeof(int)*MAX, MS_SYNC );
102 
103 free( array );
104 
105 close( fd );
106 
107 gettimeofday( &tv2, NULL );
108 
109 printf( "Time of mmap: %dms/n", tv2.tv_usec-tv1.tv_usec );
110 
111  
112 
113 return 0;
114 
115 }

?

輸出結果:

Time of read/write: 154msTime of mmap: 68ms

?

轉載于:https://www.cnblogs.com/wanpengcoder/articles/5306688.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/396525.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396525.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396525.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

判斷一個指針有沒有free_Free Code Camp的每個人現在都有一個檔案袋

判斷一個指針有沒有freeby freeCodeCamp通過freeCodeCamp Free Code Camp的每個人現在都有一個檔案袋 (Everyone at Free Code Camp now has a Portfolio) Note: we originally published this on our now-defunct blog in January of 2015.注意&#xff1a;我們最初是在2015年…

冒泡、快速排序小結

1.冒泡排序 (1) 比較領近的兩個數 (2) 如果左邊的比右邊的數字大&#xff0c;則交換位置 (3) 向右移動一位&#xff0c;繼續比較相鄰的兩個數 排序示例&#xff1a; 一輪排序結束后&#xff0c;最大值的位置已經移動最右端&#xff0c;再次如此循環&#xff0c;最終經過n-1次則…

python中until函數_等待應用程序窗口:python中的pywinauto.timings.WaitUntilPasses

我試圖在pywinauto中使用waituntilpasses來給應用程序時間打開一個新窗口.我已使用SWAPY識別窗口詳細信息.為了進行測試,我手動打開了子窗口,因此WaitUntilPasses應該立即看到該窗口,但是沒有看到.語法顯示為OK,因為我可以找到并打印find_windows的輸出,如下所示&#xff1a;xx…

synchronized 異常_由淺入深,Java 并發編程中的 Synchronized

synchronized 作用synchronized 關鍵字是 Java 并發編程中線程同步的常用手段之一。1.1 作用&#xff1a;確保線程互斥的訪問同步代&#xff0c;鎖自動釋放&#xff0c;多個線程操作同個代碼塊或函數必須排隊獲得鎖&#xff0c;保證共享變量的修改能夠及時可見&#xff0c;獲得…

mysql正則通配符全解_mysql正則表達式與通配符

擴展正則表達式的一些字符是&#xff1a; “.”匹配任何單個的字符。 一個字符類“[...]”匹配在方括號內的任何字符。例如&#xff0c;“[abc]”匹配“a”、“b”或“c”。為了命名字符的一個范圍&#xff0c;使用一個“-”。“[a-z]”匹配任何小寫字母&#xff0c;而“[0-9…

dos常用文件操作命令

1、DIR 含義&#xff1a; 顯示指定目錄下的文件和子目錄列表 類型&#xff1a; 內部命令 格式&#xff1a; DIR[drive:][path][filename][/p][/w][/A[[:]attributes]][/O[[:]sortorder]][/S][/B][/L] 舉例&#xff1a; DIR DIR D:\px2 DIR D:\px2\*.txt DIR /A:D /O:D 2、COPY…

使您的Java代碼聞起來很新鮮

by Marco Massenzio由Marco Massenzio 使您的Java代碼聞起來很新鮮 (Make your Java code smell nice and fresh) A few years ago I joined a startup working on a cloud enterprise service that was originally built by an offshore team.幾年前&#xff0c;我加入了一家…

MySQL時間戳與日期格式的相互轉換

MySQL時間戳與日期格式的相互轉換&#xff0c;PHP時間戳與日期格式的相互轉換 MySQL: 獲取當前時間SELECT NOW(); // 2018/10/11 14:22:51 時間日期格式轉換成時間戳格式&#xff0c;UNIX_TIMESTAMP()SELECT UNIX_TIMESTAMP(NOW()); // 1539238930 時間戳格式轉換成時間日期格式…

Linux內存分配機制之伙伴系統和SLAB

轉載請注明原文地址&#xff1a;http://www.cnblogs.com/ygj0930/p/6539590.html 內核內存管理的一項重要工作就是如何在頻繁申請釋放內存的情況下&#xff0c;避免碎片的產生。這就要求內核采取靈活而恰當的內存分配策略。通常&#xff0c;內存分配一般有兩種情況&#xff1a…

this.$modal.confirm 自定義按鈕關閉_自定義函數,讓你玩轉Excel得心應手

讓“自動更正”輸入統一的文本&#xff0c;你是不是經常為輸入某些固定的文本,如《電腦報》而煩惱呢?那就往下看吧。1.執行“工具→自動更正”命令,打開“自動更正”對話框。2.在“替換”下面的方框中輸入“pcw”(也可以是其他字符,“pcw”用小寫),在“替換為”下面的方框中輸…

php mysql 排名算法_MySQL PHP:優化排名查詢和計數子查詢

這是原始數據,并希望根據得分(count(tbl_1.id))對它們進行排名.[tbl_1]id | name1 | peter2 | jane1 | peter2 | jane3 | harry3 | harry3 | harry3 | harry4 | ron因此,制作臨時表(tbl_2)來計算每個id的分數.SELECT id, name, COUNT( id ) AS scoreFROM tbl_1GROUP BY idORDER…

CCF-CSP 最大的矩形

問題描述在橫軸上放了n個相鄰的矩形&#xff0c;每個矩形的寬度是1&#xff0c;而第i&#xff08;1 ≤ i ≤ n&#xff09;個矩形的高度是hi。這n個矩形構成了一個直方圖。例如&#xff0c;下圖中六個矩形的高度就分別是3, 1, 6, 5, 2, 3。請找出能放在給定直方圖里面積最大的矩…

Stack Overflow 2016年對50,000名開發人員進行的調查得出的見解

Today, Stack Overflow released the results of their 2016 survey of more than 50,000 developers.今天&#xff0c;Stack Overflow發布了他們2016年對50,000多名開發人員進行的調查的結果。 I’ve combed through this big document to bring you the most surprising ins…

web管理

1.站點根目錄下查找是否被放置webshell***根據語句判斷是不是PHP***腳本# find /storage/www/ -name "*.php" | xargs grep-in --color "eval("# grep -i --include*.php -r system\s*\( /storage/www/2.統計訪問日志中來自同ip出現的次數分析盜鏈、***、機…

MySQL的主從復制云棲社區_MySQL-主從復制

前言前篇說了作為運維在數據庫塊最起碼要會兩大技能&#xff0c;今天來說說第二技能--主從復制隨著業務的增長&#xff0c;一臺數據庫服務器以滿足不了需求了&#xff0c;負載過重&#xff0c;這時候就需要減壓&#xff0c;實現負載均衡讀寫分離&#xff0c;一主一從或一主多從…

數據存儲(SharedPreferences存儲)

SharedPreferences是通過 鍵值對 的方式存儲數據SharedPreferences是通過鍵值對的方式存儲的 將數據存儲到SharedPreferences中有3種方法&#xff1a;1.Context類中的getSharedPreferences()方法2.Activity類中的getPreferences()方法3.PreferencesManager類中的getDefaultShar…

編程程序的名稱要記住嗎_學習編程時要記住的5件事

編程程序的名稱要記住嗎by Kurt由庫爾特 學習編程時要記住的5件事 (5 Things to Remember When You’re Learning to Program) Learning to program is challenging. Aside from choosing a language or setting up a development environment that you know nothing about, t…

mysql 數據分析的步驟_數據分析8個主要步驟

# 在對數據進行分析時&#xff0c;主要細分為明確目標、應用思維和如下8個具體步驟&#xff1a;1、讀取數據2、清洗數據3、操作數據4、轉換數據5、整理數據6、分析數據7、展現數據8、總結報告接下來將介紹使用python來具體處理數據&#xff0c;包括上面幾個步驟的實現&#xff…

python學習的一個定位_python學習之——selenium元素定位

web自動化測試按步驟拆分&#xff0c;可以分為四步操作&#xff1a;定位元素&#xff0c;操作元素&#xff0c;獲取返回結果&#xff0c;斷言(返回結果與期望結果是否一致)&#xff0c;最后自動出測試報告。其中定位元素尤為關鍵&#xff0c;此篇是使用webdriver通過頁面各個元…

Invoker

Invoker 是實體&#xff0c;dubbo外其他對象的轉化。轉載于:https://www.cnblogs.com/gtaxmjld/p/9786894.html