1、特點:
① 程序相關的
② 與XSI共享記憶體一樣,需要與同步原語一起使用
③ 隻能是有共同祖先的程序才能使用
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()實作共享記憶體的通信方式有許多特點和要注意的地方,可以參看UNIX網絡程式設計第二卷。【3】
(2)使用特殊檔案提供匿名記憶體映射:
适用于具有親緣關系的程序之間。由于父子程序特殊的親緣關系,在父程序中先調用mmap(),然後調用fork()。那麼在調用fork()之後,子程序繼承父程序匿名映射後的位址空間,同樣也繼承mmap()傳回的位址,這樣,父子程序就可以通過映射區域進行通信了。一般來說,子程序單獨維護從父程序繼承下來的一些變量。而mmap()傳回的位址,卻由父子程序共同維護。對于具有親緣關系的程序實作共享記憶體最好的方式應該是采用匿名記憶體映射的方式。此時,不必指定具體的檔案,隻要設定相應的标志即可。
3、說明
(1)void *mmap(void *addr, size_t len, int prot, int flag, int fd, off_t offset );
把檔案或裝置映射或解除映射到記憶體中
0)flag:必須有MAP_SHARED 标志
MAP_SHARED對映射區域的寫入資料會複制回檔案内,而且允許其他映射該檔案的程序共享。
MAP_PRIVATE 對映射區域的寫入操作會産生一個映射檔案的複制,即私人的“寫入時複制”(copy on write)對此區域作的任何修改都不會寫回原來的檔案内容。
MAP_ANONYMOUS建立匿名共享。此時會忽略參數fd(fd可以指定為-1),不涉及檔案,而且映射區域無法和其他程序共享(隻能用于具有親緣關系的程序間通信)。
映射/dev/zero可為調用程式提供零填充的虛拟記憶體塊。
1)start:指向欲映射的記憶體起始位址,通常設為 NULL,代表讓系統自動標明位址,映射成功後傳回該位址。
2)length:代表将檔案中多大的部分映射到記憶體。
3)offset 必須是頁面大小的整數倍。頁面大小由 getpagesize(2)得到。
4)被映射的檔案大小應是頁面大小的整數倍。如一個檔案大小不是頁面大小的整數倍,映射時多出來的區域将被賦為0,對這些區域的寫不會被寫回到檔案中。
5)munmap()系統調用将删除指定位址範圍内的映射區域。随後對這個範圍内區域的引用将産生非法的記憶體引用。當這個程序終止後,這個區域也會被删除。另一方面,關閉檔案描述符并不會删除映射區域。
6)fd:要映射到記憶體中的檔案描述符。如果使用匿名記憶體映射時,即flags中設定了MAP_ANONYMOUS,fd設為-1。有些系統不支援匿名記憶體映射,則可以使用fopen打開/dev/zero檔案,然後對該檔案進行映射,可以同樣達到匿名記憶體映射的效果。
7)若映射成功則傳回映射區的記憶體起始位址,否則傳回MAP_FAILED(-1)。
(2) munmap
int munmap( void * addr, size_t len )
在程序位址空間中解除一個映射關系,當映射關系解除後,對原來映射位址的通路将導緻段錯誤發生。
void * addr :調用mmap()時傳回的位址
size_t len :映射區的大小
(3)int msync ( void * addr , size_t len, int flags)
一般說來,程序在映射空間的對共享内容的改變并不直接寫回到磁盤檔案中,往往在調用munmap()後才執行該操作。可以調用msync()實作磁盤上檔案與共享記憶體區的内容一緻。
int flags :MS_ASYN: 異步寫,MS_SYN : 同步寫,MS_INVALIDAT : 無效的cache 資料。
4、示例
示例1

View Code
示例2

mmap_w

mmap_r
5、其他
1)程序調用mmap()時,隻是在程序空間内新增了一塊相應大小的緩沖區,并設定了相應的通路辨別,但并沒有建立程序空間到實體頁面的映射。是以,第一次通路該空間時,會引發一個缺頁異常。
2)一個共享記憶體區域可以看作是特殊檔案系統shm中的一個檔案,shm的安裝點在交換區上。
3)mmap()系統調用使得程序之間通過映射同一個普通檔案實作共享記憶體。普通檔案被映射到程序位址空間後,程序可以向通路普通記憶體一樣對檔案進行通路,不必再調用read(),write()等操作。
4)最終被映射檔案的内容的長度不會超過檔案本身的初始大小,即映射不能改變檔案的大小。檔案被映射部分而不是整個檔案決定了程序能夠通路的空間大小,另外,如果指定檔案的偏移部分,一定要注意為頁面大小的整數倍。
<a href="http://files.cnblogs.com/mydomain/%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98.pdf">總結文檔</a>
參考
【2】 對定義作了詳細的講解
<a href="http://hi.baidu.com/zmjdx/blog/item/ede7e52ac0734892023bf678.html">http://hi.baidu.com/zmjdx/blog/item/ede7e52ac0734892023bf678.html</a>
【3】 unix網絡程式設計中講解
<a href="http://blog.chinaunix.net/space.php?uid=9185047&do=blog&cuid=2282785">http://blog.chinaunix.net/space.php?uid=9185047&do=blog&cuid=2282785</a>
【4】 台灣某大學的網頁
<a href="http://pws.niu.edu.tw/~ttlee/2010.os.day/memory.map2/">http://pws.niu.edu.tw/~ttlee/2010.os.day/memory.map2/</a>
【5】 舉的一個非常形象的例子
<a href="http://www.ncad.co.jp/~komata/c-kouza20.htm">http://www.ncad.co.jp/~komata/c-kouza20.htm</a>