https://blog.csdn.net/u012232736/article/details/80351813
https://www.cnblogs.com/xcywt/p/5128430.html
一,共享内存
内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即共享内存。
映射物理内存叫挂接,用完以后解除映射叫脱接。
1,共享内存的特点:
优点:是最快的IPC。
缺点:要编程者自己实现对共享内存互斥访问。如何实现?
2,编程模型:具体函数的用法可以用man手册查看(强力推荐)
3 ,实现共享内存的步骤如下:(linux)
(1) 创建内存共享区 进程1通过操作系统提供的api从内存中申请一块共享区域,linux系统中可以通过shmget函数实现,生成的共享内存块与某个特定的key进行绑定。
(2) 映射共享内存到进程1中
在linux环境中,可以通过shmat实现。
(3)映射共享内存到进程2中
进程2通过进程1的shmget函数和同一个key值,然后执行shmat,将这个内存映射到进程2中。
(4)进程1与进程2中相互通信
共享内存实现两个映射后,可以利用该区域进行信息交换,由于没有同步机制,需要参与通信的进程自己协商处理。
(5)撤销内存映射关系
完成通信之后,需要撤销之前的映射操作,通过shmdt函数实现。
(6)删除共享内存区
在linux中通过shmctl函数来实现。
4.实例:
进程A: writeshm.c
1) 获得key, ftok()
2) 使用key来创建一个共享内存 shmget()
3) 映射共享内存(得到虚拟地址), shmat()
4) 使用共享内存, 往共享内存中写入数据
5) 解除映射 shmdt()
6) 如果共享内存不再使用,可以使用shmctl()销毁共享内存
进程B: readshm.c
1) 获得key, ftok()
2) 使用key来获得一个共享内存 shmget()
3) 映射共享内存(得到虚拟地址), shmat()
4) 使用共享内存, 读取共享内存中的数据
5) 解除映射 shmdt()
3,实例
进程A:
// writeshm.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
// 生成一个key
key_t key = ftok("./", 66);
// 创建共享内存,返回一个id
int shmid = shmget(key, 8, IPC_CREAT|0666|IPC_EXCL);
if(-1 == shmid)
{
perror("shmget failed");
exit(1);
}
// 映射共享内存,得到虚拟地址
void *p = shmat(shmid, 0, 0);
if((void*)-1 == p)
{
perror("shmat failed");
exit(2);
}
// 写共享内存
int *pp = p;
*pp = 0x12345678;
*(pp + 1) = 0xffffffff;
// 解除映射
if(-1 == shmdt(p))
{
perror("shmdt failed");
exit(3);
}
printf("解除映射成功,点击回车销毁共享内存\n");
getchar();
// 销毁共享内存
if(-1 == shmctl(shmid, IPC_RMID, NULL))
{
perror("shmctl failed");
exit(4);
}
return 0;
}
进程B:
// readshm.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
// 生成一个key
key_t key = ftok("./", 66);
// 获取共享内存,返回一个id
int shmid = shmget(key, 0, 0);
if(-1 == shmid)
{
perror("shmget failed");
exit(1);
}
// 映射共享内存,得到虚拟地址
void *p = shmat(shmid, 0, 0);
if((void*)-1 == p)
{
perror("shmat failed");
exit(2);
}
// 读共享内存
int x = *(int *)p;
int y = *((int *)p + 1);
printf("从共享内存中都取了:0x%x 和 0x%x \n", x, y);
// 解除映射
if(-1 == shmdt(p))
{
perror("shmdt failed");
exit(3);
}
return 0;
}