版权声明:guojawee https://blog.csdn.net/weixin_36750623/article/details/83384612
1.最快的IPC通信方式
共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这 些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调 用来传递彼此的数据。
图:用管道或者消息队列传递数据
图:用共享内存传递数据
2.相关API
[1]shmget
int shmget(key_t key, size_t size, int shmflg); //创建或打开
[2]shmat:将共享内存段连接到进程地址空间
[说明]shmget创建/打开共享内存后,必须使用shmat将该共享内存连接到 进程的地址空间,以便进程使用。不适用shmat,进程无法使用该共享内存。 (每个进程shmat以后得到的地址不一样--属于自己的共享内存地址) p=shmat(shm_id,NULL,0);//让本进程链接到共享内存会得到一个共享内存的首地址p,可 以直接通过指针p去操控共享内存。 ----------------------------------- void *shmat(int shmid, const void *shmaddr, int shmflg); 参数: shmaddr:指定连接的地址 shmflg:两个可能取值SHM_RND和SHM_RDONLY 返回值:失败返回-1;成功返回一个指针p(指向共享内存的第一个字节),使用p操 控共享内存。
shmaddr和shmflg的组合关系 | 共享内存最终地址 |
---|---|
shmaddr为NULL,不管shmflg | 核心自动选择一个地址 |
shmaddr不为NULL且shmflg无SHM_RND标记 | 以shmaddr为连接地址 |
shmaddr不为NULL且shmflg设置了SHM_RND标记 | 连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA) |
shmflg=SHM_RDONLY | 表示连接操作用来只读共享内存 |
[3]shmdt:将共享内存段与当前进程脱离
int shmdt(const void *shmaddr); 参数shmaddr:由shmat所返回的指针
注意:将共享内存段与当前进程脱离不等于删除共享内存段
[3]shmctl:控制共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf); IPC_STAT:获取shmid_ds结构中的值 IPC_SET:设置shmid_ds结构中的值 IPC_RMID:删除共享内存
3.共享内存的删除[难点]
1.如果共享内存被别的程序占用,连接数/引用计数不为0,则删除共享内存不会立马被 删除====>删除后,会出现一个现象---共享内存key值变成了0,引用计数减1---且此时 的共享内存已经不能被其他[新shmat]的进程读取了(重启一个进程重新shmat的时候 由于key已经变为0,所以新开的进程是不能再继续读取共享内存的数据的);只能被 在删除之前就[已经shmat]的进程读取。 2.只有当连接共享内存的所有进程都死掉,Linux内核才会删除共享内存 --------------------------------- 总结:是否能直接删除共享内存? 关键是看在删除以后有无进程链接到该块内存<==>等同于shmctl+shmdt删除之前有 多少进程已经执行了shmat。
示例代码
子进程向shm中写数据 父进程从shm中读取子进程向shm写入的数据
typedef struct student{ int age; char name[10]; }student; int main() { key_t key=ftok("/home/gjw/tmp",'a'); int shm_id=shmget(key,sizeof(int)*100,0664|IPC_CREAT); pid_t pid=fork(); if(pid>0) { } else if(pid==0) { void* ptr=shmat(shm_id,NULL,0); struct student* stu=(struct student*)ptr; stu->age=24; strcpy(stu->name,"guojiawei"); shmdt(ptr); exit(0); } sleep(1); wait(NULL); void* ptr=shmat(shm_id,NULL,0); printf("age=%d, name=%s\n",((student*)ptr)->age,((student*)ptr)->name); shmdt(ptr); return 0; }
文章来源: 4.共享内存shm