mmap和shm共享內存的區別和聯繫

共享內存的建立html

根據理論:linux

 1. 共享內存容許兩個或多個進程共享一給定的存儲區,由於數據不須要來回複製,因此是最快的一種進程間通訊機制。共享內存能夠經過mmap()映射普通文件(特殊狀況下還能夠採用匿名映射)機制實現,也能夠經過系統V共享內存機制實現。應用接口和原理很簡單,內部機制複雜。爲了實現更安全通訊,每每還與信號燈等同步機制共同使用。

mmap的機制如:就是在磁盤上創建一個文件,每一個進程存儲器裏面,單獨開闢一個空間來進行映射。若是多進程的話,那麼不會對實際的物理存儲器(主存)消耗太大。


nginx

shm的機制:每一個進程的共享內存都直接映射到實際物理存儲器裏面。windows


結論:

一、mmap保存到實際硬盤,實際存儲並無反映到主存上。優勢:儲存量能夠很大(多於主存)(這裏一個問題,須要高手解答,會不會太多拷貝到主存裏面???);缺點:進程間讀取和寫入速度要比主存的要慢。

二、shm保存到物理存儲器(主存),實際的儲存量直接反映到主存上。優勢,進程間訪問速度(讀寫)比磁盤要快;缺點,儲存量不能很是大(多於主存)

使用上看:若是分配的存儲量不大,那麼使用shm;若是存儲量大,那麼使用shm。



緩存

參看百度:http://baike.baidu.com/view/1499209.htm安全

mmap就是一個文件操做函數

 

看這些百度的描述:測試

mmap()系統調用使得進程之間經過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程能夠向訪問普通內存同樣對文件進行訪問,沒必要再調用read(),write()等操做。 成功執行時,mmap()返回被映射區的指針,munmap()返回0。失敗時,mmap()返回MAP_FAILED[其值爲(void *)-1],munmap返回-1。errno被設爲如下的某個值 EACCES:訪問出錯EAGAIN:文件已被鎖定,或者太多的內存已被鎖定EBADF:fd不是有效的文件描述詞EINVAL:一個或者多個參數無效 ENFILE:已達到系統對打開文件的限制ENODEV:指定文件所在的文件系統不支持內存映射ENOMEM:內存不足,或者進程已超出最大內存映射數量 EPERM:權能不足,操做不容許ETXTBSY:已寫的方式打開文件,同時指定MAP_DENYWRITE標誌SIGSEGV:試着向只讀區寫入 SIGBUS:試着訪問不屬於進程的內存區參數fd爲即將映射到進程空間的文件描述字,大數據

 

通常由open()返回,同時,fd能夠指定爲-1,此時須指定 flags參數中的MAP_ANON,代表進行的是匿名映射(不涉及具體的文件名,避免了文件的建立及打開,很顯然只能用於具備親緣關係的進程間通訊)網站

 

相關文章參考:

 

mmap函數是unix/linux下的系統調用,來看《Unix Netword programming》卷二12.2節有詳細介紹。

mmap系統調用並非徹底爲了用於共享內存而設計的。它自己提供了不一樣於通常對普通文件的訪問方式,進程能夠像讀寫內存同樣對普通文件的操做。而Posix或系統V的共享內存IPC則純粹用於共享目的,固然mmap()實現共享內存也是其主要應用之一。
          mmap系統調用使得進程之間經過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程能夠像訪問普通內存同樣對文件進行訪問,沒必要再 調用read(),write()等操做。mmap並不分配空間, 只是將文件映射到調用進程的地址空間裏, 而後你就能夠用memcpy等操做寫文件, 而不用write()了.寫完後用msync()同步一下, 你所寫的內容就保存到文件裏了. 不過這種方式沒辦法增長文件的長度, 由於要映射的長度在調用mmap()的時候就決定了.

簡單說就是把一個文件的內容在內存裏面作一個映像,內存比磁盤快些。
基本上它是把一個檔案對應到你的virtual memory 中的一段,並傳回一個指針。

 

 

 

 

重寫總結:

一、mmap實際就是操做「文件」。

二、映射文件,除了主存的考慮外。shm的內存共享,效率應該比mmap效率要高(mmap經過io和文件操做,或「須要寫完後用msync()同步一下」);固然mmap映射操做文件,比直接操做文件要快些;因爲多了一步msync應該能夠說比shm要慢了吧???

三、另外一方面,mmap的優勢是,操做比shm簡單(沒有調用比shm函數複雜),我想這也是許多人喜歡用的緣由,包括nginx。

 

缺點,還得經過實際程序測試,肯定!!!

 

修正理解(這也真是的,這個網站沒辦法附加;只能重寫了):

今天又細心研究了一下,發現百度這麼一段說明:

二、系統調用mmap()用於共享內存的兩種方式: 
(1)使用普通文件提供的內存映射:適用於任何進程之間;此時,須要打開或建立一個文件,而後再調用mmap();典型調用代碼以下: 
fd=open(name, flag, mode); 
if(fd<0) 
... 
ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0); 經過mmap()實現共享內存的通訊方式有許多特色和要注意的地方,咱們將在範例中進行具體說明。 
(2)使用特殊文件提供匿名內存映射:適用於具備親緣關係的進程之間;因爲父子進程特殊的親緣關係,在父進程中先調用mmap(),而後調用fork()。那麼在調用fork()以後,子進程繼承父進程匿名映射後的地址空間,一樣也繼承mmap()返回的地址,這樣,父子進程就能夠經過映射區域進行通訊了。注意,這裏不是通常的繼承關係。通常來講,子進程單獨維護從父進程繼承下來的一些變量。而mmap()返回的地址,卻由父子進程共同維護。

看了一下windows「內存映射文件」:http://baike.baidu.com/view/394293.htm

內存映射文件與虛擬內存有些相似,經過內存映射文件能夠保留一個地址空間的區域,同時將物理存儲器提交給此區域,只是內存文件映射的物理存儲器來自一個已經存在於磁盤上的文件,而非系統的頁文件,並且在對該文件進行操做以前必須首先對文件進行映射,就如同將整個文件從磁盤加載到內存。由此能夠看出,使用內存映射文件處理存儲於磁盤上的文件時,將沒必要再對文件執行I/O操做,這意味着在對文件進行處理時將沒必要再爲文件申請並分配緩存,全部的文件緩存操做均由系統直接管理,因爲取消了將文件數據加載到內存、數據從內存到文件的回寫以及釋放內存塊等步驟,使得內存映射文件在處理大數據量的文件時能起到至關重要的做用。另外,實際工程中的系統每每須要在多個進程之間共享數據,若是數據量小,處理方法是靈活多變的,若是共享數據容量巨大,那麼就須要藉助於內存映射文件來進行。實際上,內存映射文件正是解決本地多個進程間數據共享的最有效方法。

 

這裏再總結一次:

一、mmap有兩種方式,一種是映射內存,它把普通文件映射爲實際物理內存頁,訪問它就和訪問物理內存同樣(這也就和shm的功能同樣了)(同時不用刷新到文件)

二、mmap能夠映射文件,不肯定會不會像windows「內存映射文件」同樣的功能,若是是,那麼他就能映射好幾G甚至好幾百G的內存數據,對大數據處理將提供強大功能了???

三、shm只作內存映射,和mmap第一個功能同樣!只不過不是普通文件而已,但都是物理內存。

 

但願你們出意見!!!

 轉載地址:http://blog.chinaunix.net/uid-16979052-id-3494641.html

相關文章
相關標籤/搜索