在管道、信號、消息隊列、Socket 等 IPC 方式中,共享內存速度最快。一旦內存區映射到進程地址空間,資料傳遞不再經過內核,極大降低複製開銷。但需注意:多進程並發讀寫必須配合同步機制(如信號量)保護關鍵區。
shm_open / open + mmap 建立映射munmap 解除映射msync 刷新至磁碟shm_unlink 移除物件tmpfs 下的檔案)MAP_ANON,適用於有親緣關係的進程)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
flags 包含 MAP_ANON,fd 傳 -1 即可,無需打開檔案。
ftruncate 動態調整。shmget 獲取/建立共享內存標識符shmat 掛接至進程地址空間shmdt 脫離掛接shmctl 控制操作(如刪除 IPC_RMID)/proc/sys/kernel/ 或 ipcs 查看)shmmax:單個段最大位元組數shmmin:最小位元組數shmmni:系統範圍內最大段數shmseg:單進程最大掛接段數| 維度 | POSIX (mmap) | System V |
|---|---|---|
| 建立方式 | 需開啟檔案 | 鍵值直接建立 |
| 進程間同步 | 需約定鍵或傳遞 fd | 統一 key 標識 |
| 讀寫速度 | 略低 | 通常更高 |
| 容量限制 | 受檔案系統/記憶體限制 | 受核心參數限制,不可過大 |
無論哪種方式,多進程讀寫都必須互斥。常用 POSIX 信號量:
sem_init(&mutex, 1, 1); // 進程間共享
sem_wait(&mutex); // 加鎖
sem_post(&mutex); // 解鎖
// 編譯需鏈接 -lpthread
#include <sys/mman.h> #include <fcntl.h> #include <semaphore.h>
#define FILE "/tmp/cluster_share"
struct Data { sem_t mutex; int arr[10]; } *ptr;
int fd = open(FILE, O_CREAT|O_RDWR|O_TRUNC, 0777);
lseek(fd, sizeof(struct Data)-1, SEEK_SET); write(fd, "", 1);
ptr = mmap(NULL, sizeof(*ptr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
sem_init(&ptr->mutex, 1, 1);
while(1) { sem_wait(&ptr->mutex); /* 寫入 */ sem_post(&ptr->mutex); sleep(1); }
int fd = open(FILE, O_RDWR);
ptr = mmap(NULL, sizeof(*ptr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
while(1) { sem_wait(&ptr->mutex); /* 讀取 */ sem_post(&ptr->mutex); sleep(1); }
#include <sys/shm.h> #include <semaphore.h>
int shmid = shmget(12345, sizeof(struct Data), 0666|IPC_CREAT);
void *shm = shmat(shmid, 0, 0);
struct Data *ptr = (struct Data*)shm;
sem_init(&ptr->mutex, 1, 1);
while(1) { sem_wait(&ptr->mutex); /* 寫入 */ sem_post(&ptr->mutex); sleep(1); }
int shmid = shmget(12345, sizeof(struct Data), 0666);
void *shm = shmat(shmid, 0, 0);
struct Data *ptr = (struct Data*)shm;
while(1) { sem_wait(&ptr->mutex); /* 讀取 */ sem_post(&ptr->mutex); sleep(1); }
tmpfs、易於除錯)。