mmap和shm共享記憶體的區別和聯絡
共享記憶體的建立
根據理論:
1. 共享記憶體允許兩個或多個程序共享一給定的儲存區,因為資料不需要來回複製,所以是最快的一種程序間通訊機制。共享記憶體可以通過mmap()對映普通檔案(特殊情況下還可以採用匿名對映)機制實現,也可以通過系統V共享記憶體機制實現。應用介面和原理很簡單,內部機制複雜。為了實現更安全通訊,往往還與訊號燈等同步機制共同使用。mmap的機制如:就是在磁碟上建立一個檔案,每個程序儲存器裡面,單獨開闢一個空間來進行對映。如果多程序的話,那麼不會對實際的物理儲存器(主存)消耗太大。
shm的機制:每個程序的共享記憶體都直接對映到實際物理儲存器裡面。
結論:
1、mmap儲存到實際硬碟,實際儲存並沒有反映到主存上。優點:儲存量可以很大(多於主存)(這裡一個問題,需要高手解答,會不會太多拷貝到主存裡面???);缺點:程序間讀取和寫入速度要比主存的要慢。
2、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 中的一段,並傳回一個指標。
重寫總結:
1、mmap實際就是操作“檔案”。
2、對映檔案,除了主存的考慮外。shm的記憶體共享,效率應該比mmap效率要高(mmap通過io和檔案操作,或“需要寫完後用msync()同步一下”);當然mmap對映操作檔案,比直接操作檔案要快些;由於多了一步msync應該可以說比shm要慢了吧???
3、另一方面,mmap的優點是,操作比shm簡單(沒有呼叫比shm函式複雜),我想這也是許多人喜歡用的原因,包括nginx。
缺點,還得通過實際程式測試,確定!!!
修正理解(這也真是的,這個網站沒辦法附加;只能重寫了):
今天又細心研究了一下,發現百度這麼一段說明:
2、系統呼叫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()返回的地址,卻由父子程序共同維護。
這裡再總結一次:
1、mmap有兩種方式,一種是對映記憶體,它把普通檔案對映為實際實體記憶體頁,訪問它就和訪問實體記憶體一樣(這也就和shm的功能一樣了)(同時不用重新整理到檔案)
2、mmap可以對映檔案,不確定會不會像windows“記憶體對映檔案”一樣的功能,如果是,那麼他就能對映好幾G甚至好幾百G的記憶體資料,對大資料處理將提供強大功能了???
3、shm只做記憶體對映,和mmap第一個功能一樣!只不過不是普通檔案而已,但都是實體記憶體。