1.簡介
共享內存可以說是最有用的進程間通信方式.兩個不用的進程共享內存的意思是:同一塊物理內存被映射到兩個進程的各自的進程地址空間.一個進程可以及時看到另一個進程對共享內存的更新,反之亦然.
采用共享內存通信的一個顯而易見的好處效率高,因為進程可以直接讀寫內存,而不需要任何數據的復制.對於向管道和消息隊列等通信等方式,則需要在內核和用戶空間進行四次的數據復制,而共享內存則只需要兩次數據復制:一次從輸入文件到共享內存區,另一個從共享內存區到輸出文件.實際上,進程之間在共享內存時,並不總是讀寫少量數據後就解除映射,有新的通信時,再重新建立共享內存區域.而是保持共享區域,知道通信完畢為止,這樣,數據內容就一直保存在共享內存中,並沒有寫回文件.共享內存中的內容往往是在解除映射時才寫回文件的.因此,采用共享內存的通信方式效率非常高.
linux從2.2內核開始就支持多種共享內存方式,如mmap系統調用,Posix共享內存,以及System V共享內存.本文主要介紹mmap系統調用的原理及應用.後續的文章會講解System V共享內存.
2.mmap系統調用
mmap系統調用是的是的進程間通過映射同一個普通文件實現共享內存.普通文件被映射到進程地址空間後,進程可以向像訪問普通內存一樣對文件進行訪問,不必再調用read,write等操作.與mmap系統調用配合使用的系統調用還有munmap,msync等.
實際上,mmap系統調用並不是完全為了用於共享內存而設計的.它本身提供了不同於一般對普通文件的訪問方式,是進程可以像讀寫內存一樣對普通文件操作.而Posix或System V的共享內存則是純粹用於共享內存的,當然mmap實現共享內存也是主要應用之一.
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
各個參數的說明如下:
函數的返回值為最後文件映射到進程空間的地址,進程可以直接操作起始地址為該值的有效地址.系統調用mmap用於共享內存時有下面兩種常用的方式:
1)使用普通文件提供的內存映射:適用於任何進程之間.此時,需要打開或創建一個文件,然後再調用mmap,這種方式有許多特點和要注意的地方,我們在後面或舉例子說明.
2)使用特殊文件提東匿名內存映射:適用於具有親緣關系的進程之間.由於父子進程特殊的親緣關系,在父進程中吊牌用mmap,然後調用fork.那麼在調用fork之後,子進程急促繼承父進程匿名映射後的地址空間,同樣也繼承mmap返回的地址,這樣,父子進程就可以通過映射區進行通信了.注意,mmap返回的地址,需要由父進程共同維護.
對於任意的兩個進程可以使用第一種方式,而對於具有親緣關系的進程實現共享內存最好的方式應該是采用匿名內存映射的方式.此時,不必指定具體的文件,只要設定相應的標志即可,後面有相應的例子.
更多詳情請繼續閱讀第2頁的內容:http://www.linuxidc.com/Linux/2013-10/91443p2.htm