DESCRIPTION
共享內存是最快的可用IPC形式。它允許多個不相關(無親緣關系)的進程去訪問同一部分邏輯內存。
如果需要在兩個進程之間傳輸數據,共享內存將是一種效率極高的解決方案。一旦這樣的內存區映射到共享它的進程的地址空間,這些進程間數據的傳輸就不再涉及內核。這樣就可以減少系統調用時間,提高程序效率。
共享內存是由IPC為一個進程創建的一個特殊的地址范圍,它將出現在進程的地址空間中。其他進程可以把同一段共享內存段“連接到”它們自己的地址空間里去。所有進程都可以訪問共享內存中的地址。如果一個進程向這段共享內存寫了數據,所做的改動會立刻被有訪問同一段共享內存的其他進程看到。
要注意的是共享內存本身沒有提供任何同步功能。也就是說,在第一個進程結束對共享內存的寫操作之前,並沒有什么自動功能能夠預防第二個進程開始對它進行讀操作。共享內存的訪問同步問題必須由程序員負責。可選的同步方式有互斥鎖、條件變量、讀寫鎖、紀錄鎖、信號燈。
實際上,進程之間在共享內存時,並不總是讀寫少量數據后就解除映射,有新的通信時,再重新建立共享內存區域。而是保持共享區域,直到通信完畢為止。
POSIX Shared Memory API
使用POSIX共享內存需要用到下面這些API:
#include <sys/types.h> #include <sys/stat.h> /* For mode constants */ #include <sys/mman.h> #include <fcntl.h> /* For O_* constants */ #include <unistd.h> int shm_open(const char *name, int oflag, mode_t mode); int shm_unlink(const char *name); int ftruncate(int fildes, off_t length); void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); int munmap(void *addr, size_t len); int close(int fildes); int fstat(int fildes, struct stat *buf); int fchown(int fildes, uid_t owner, gid_t group); int fchmod(int fildes, mode_t mode);
shm_open
穿件並打開一個新的共享內存對象或者打開一個既存的共享內存對象, 與函數open的用法是類似的. 函數返回值是一個文件描述符,會被下面的API使用.
ftruncate
設置共享內存對象的大小,新創建的共享內存對象大小為0.
mmap
將共享內存對象映射到調用進程的虛擬地址空間.
munmap
取消共享內存對象到調用進程的虛擬地址空間的映射.
shm_unlink
刪除一個共享內存對象名字.
close
當shm_open函數返回的文件描述符不再使用時,使用close函數關閉它.
fstat
獲得共享內存對象屬性的stat結構體. 結構體中會包含共享內存對象的大小(st_size), 權限(st_mode), 所有者(st_uid), 歸屬組 (st_gid).
fchown
改變一個共享內存對象的所有權.
fchmod
改變一個共享內存對象的權限.
Persistence(持續性)
POSIX 共享內存隨內核持續: 共享內存對象會一直存在,直到系統關閉 或者 一個進程取消內存映射(unmapped)並且調用shm_unlink來刪除共享內存對象.
Linking(鏈接庫)
必須鏈接rt(librt)庫,也就是real-time library.
-lrt
Accessing shared memory objects via the file system
在Linux系統中, 共享內存對象是在虛擬文件系統(tmpfs)中創建的, 通常掛載在目錄 /dev/shm 下.
Linux從內核2.4 和glibc 2.2版本開始支持POSIX共享內存.
從Linux內核2.6.19版本起, Linux支持使用訪問控制列表(ACLs) 來控制虛擬文件系統中對象的權限.
Inherit
to be continued...
CONFORMING TO(遵守的彼岸准)
POSIX.1-2001.
NOTES
多進程必須使用同步機制來訪問共享內存對象, 比如使用POSIX信號量.
System V 的共享內存是過時的, POSIX共享內存提供了使用更簡單、設計更合理的API.