共享内存相关函数
获得一个共享存储标识符
#include <sys/ipc.h> #include <sys/shm.h int shmget(key_t key, size_t size, int shmflg); 返回值:成功共享存储ID,失败-1 key:函数ftok返回值或IPC_PRIVATE(适合用在有亲缘关系的进程中)
size: 共享存储段的长度,以字节为单位
shmflg:权限标志位
共享存储段执行多种操作
#include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf); 返回值:成功0错误-1 shmid:共享内存标识符 cmd: IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode赋值到共享内存的shmid_ds结构中
IPC_RMID:删除这些共享内存
buf:共享内存管理结构体
shmid_ds结构:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
struct shmid_ds { struct ipc_perm shm_perm; /* Ownership and permissions */ size_t shm_segsz; /* Size of segment (bytes) */ time_t shm_atime; /* Last attach time */ time_t shm_dtime; /* Last detach time */ time_t shm_ctime; /* Last change time */ pid_t shm_cpid; /* PID of creator */ pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */ shmatt_t shm_nattch; /* No. of current attaches */ ... };
一旦创建了一个共享存储段,进程就可调用shmat将其连接到它的地址空间中
#include <sys/types.h> #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg); 返回值:成功共享存储段的指针,失败-1 shmid:共享内存标识符 shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核决定 shmflg:如果指定了SHM_RDONLY位,则以只读方式连接此段,否则以读写的方式连接此段。通常为0
当对共享存储段的操作已经结束时,则调用shmdt与该段分离
#include <sys/types.h> #include <sys/shm.h> int shmdt(const void *shmaddr); 返回值:成功0,失败-1 shmaddr:shmat返回的值
程序例程,父子进程间通讯:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/shm.h> 4 #include <sys/ipc.h> 5 #include <string.h> 6 7 #define SIZE 1024 8 9 int main() 10 { 11 int shmid; 12 pid_t pid; 13 char *shmaddr; 14 int flag; 15 struct shmid_ds buf; 16 17 shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600); 18 if(shmid < 0) 19 { 20 perror("get shm ipc_id error"); 21 return -1; 22 } 23 24 if((pid = fork()) < 0) { 25 perror("get fork error"); 26 return -1; 27 } else if(pid == 0) { /* child */ 28 shmaddr = (char *)shmat(shmid, NULL, 0); 29 if((int)shmaddr == -1) 30 { 31 perror("shmat error"); 32 return -1; 33 } 34 strcpy(shmaddr, "Hi,I am child process! "); 35 shmdt(shmaddr); 36 return 0; 37 } else { /* parent */ 38 sleep(3); 39 flag = shmctl(shmid, IPC_STAT, &buf); 40 if(flag == -1) 41 { 42 perror("shmctl error"); 43 return -1; 44 } 45 46 printf("shm_segsz=%d bytes ", buf.shm_segsz); 47 printf("parent pid=%d,shm_cpid=%d ", getpid(), buf.shm_cpid); 48 printf("child pid=%d,shm_lpid=%d ", pid, buf.shm_lpid); 49 shmaddr = (char *)shmat(shmid, NULL, 0); 50 if((int)shmaddr == -1) 51 { 52 perror("parent:shmat error"); 53 return -1; 54 } 55 printf("shmaddr in %s ", shmaddr); 56 shmdt(shmaddr); 57 shmctl(shmid, IPC_RMID, NULL); 58 } 59 60 return 0; 61 }
进程之间使用共享内存通讯:
shmwrite.c
1 #include <stdio.h> 2 #include <sys/ipc.h> 3 #include <sys/shm.h> 4 #include <string.h> 5 6 typedef struct { 7 char name[8]; 8 int age; 9 }people; 10 11 int main() 12 { 13 int shmid; 14 key_t key; 15 char temp[8]; 16 char pathname[30]; 17 people *p_map; 18 int i; 19 20 strcpy(pathname, "/tmp"); 21 key = ftok(pathname, 0x03); 22 if(key == -1) 23 { 24 perror("ftok error "); 25 return -1; 26 } 27 28 printf("key=%d ", key); 29 shmid = shmget(key, 4096,IPC_CREAT|IPC_EXCL|0600); 30 if(shmid == -1) 31 { 32 perror("shmget error "); 33 return -1; 34 } 35 printf("shmid=%d ",shmid); 36 37 p_map = (people *)shmat(shmid, NULL, 0); 38 if((int)p_map == -1) 39 { 40 perror("shmat error "); 41 return -1; 42 } 43 memset(temp, 0x00, sizeof(temp)); 44 strcpy(temp, "test"); 45 temp[4] = '0'; 46 47 for(i=0;i<3;i++) 48 { 49 temp[4]+=1; 50 strncpy((p_map+i)->name, temp, 5); 51 (p_map+i)->age=i; 52 } 53 54 if(shmdt(p_map) == -1) 55 { 56 perror("shmdt error "); 57 return -1; 58 } 59 return 0; 60 }
shmread.c
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char name[8]; int age; }people; int main(int argc, char *argv[]) { int shmid; people *p_map; key_t key; char pathname[30]; int i = 0; strcpy(pathname, "/tmp"); key = ftok(pathname, 0x03); if(key == -1) { perror("ftok error "); return -1; } printf("key=%d ", key); shmid = shmget(key, 0, 0); if(shmid == -1) { perror("shmread:shmget error "); return -1; } printf("shmid=%d ",shmid); p_map = (people*)shmat(shmid, NULL, 0); for(i=0;i<3;i++) { printf("name:%s ", (*(p_map+i)).name); printf("age:%d ", (*(p_map+i)).age); } if(shmdt(p_map) == -1) { perror("shmdt error "); return -1; } return 0; }
然后执行:
gcc shmwrite.c -o shmwrite gcc shmread.c -o shmread ./shmwrite ./shmread