共享内存
原理:多个进程映射到同一块内存
半双工
Linux进程通信中最快的
API
1.int shmget(key_t key, size_t size, int shmflg); 用于创建或者获取共享内存
- key:不同进程使用相同的key可以获取到同一块内存
- size:创建共享内存时,指定要申请的共享内存空间大小,以字节为单位。
- shmflg:IPC_CREAT 存在则打开,不存在则创建。
- IPC_CREAT与IPC_EXCL一起使用,存在则会报错,不存在则创建
- return 成功返回共享内存的ID,失败返回-1
2.void *shmat(int shmid, const void *shmaddr, int shmflg); 将共享内存映射到进程的地址空间
shmaddr:一般给NULL,由系统自动选择映射的虚拟地址空间
shmflg:不指定时给0
return 成功返回共享内存的首地址,失败返回NULL
3.int shmdt(const void *shmaddr);断开当前进程的shmaddr指向的共享内存映射
return 成功返回0,失败返回-1
简单案例:一个进程往共享内存中写一次数据然后在另一块共享内存读一次数据,然后另一个进程在一个共享内存读一次数据在另一块共享内存写一次数据(同时验证了它是半双工的)
a.cpp
#include<iostream>
#include<unistd.h>
#include<cstring>
#include<sys/shm.h>
int main()
{
int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
if(-1 == shmid)
{
std::cout<<"shmget erro"<<std::endl;
exit(-1);
}
char * s = (char *)shmat(shmid,nullptr,0);
if(s == (char *)-1)
{
std::cout<<"shmat erro"<<std::endl;
}
int shmid2 = shmget((key_t)123457,128,IPC_CREAT|0600);
if(-1 == shmid2)
{
std::cout<<"shmget erro"<<std::endl;
exit(-1);
}
char * s2 = (char *)shmat(shmid2,nullptr,0);
if(s2 == (char *)-1)
{
std::cout<<"shmat erro"<<std::endl;
}
strcpy(s,"hello1");
sleep(1);
std::cout<<s2;
shmdt(s);
shmdt(s2);
exit(0);
}
b.cpp
#include<iostream>
#include<unistd.h>
#include<cstring>
#include<sys/shm.h>
int main()
{
int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
if(-1 == shmid)
{
std::cout<<"shmget erro"<<std::endl;
exit(-1);
}
char * s = (char *)shmat(shmid,nullptr,0);
if(s == (char *)-1)
{
std::cout<<"shmat erro"<<std::endl;
}
int shmid2 = shmget((key_t)123457,128,IPC_CREAT|0600);
if(-1 == shmid2)
{
std::cout<<"shmget erro"<<std::endl;
exit(-1);
}
char * s2 = (char *)shmat(shmid2,nullptr,0);
if(s2 == (char *)-1)
{
std::cout<<"shmat erro"<<std::endl;
}
std::cout<<s;
strcpy(s2,"hello2");
shmdt(s);
shmdt(s2);
exit(0);
}
结果
使用信号量进行同步读写
sharedmemory1.cpp
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include"sem.h"
int main()
{
int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
if(shmid == -1)
{
std::cout<<"shmget erro"<<std::endl;
exit(1);
}
char * s=(char *)shmat(shmid,NULL,0);
if(s== (char *)-1)
{
std::cout<<"shmat erro"<<std::endl;
exit(1);
}
sem_init();
while(1)
{
sem_p(SEC);
if(strncmp(s,"end",3) !=0)
{
std::cout<<s<<std::endl;
}else
{
break;
}
sem_v(FIR);
}
shmdt(s);
sem_destory();
}
sharedmemory2.cpp
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
#include"sem.h"
int main()
{
int shmid = shmget((key_t)123456,128,IPC_CREAT|0600);
if(shmid == -1)
{
std::cout<<"shmget erro\n"<<std::endl;
exit(1);
}
char * s=(char *)shmat(shmid,NULL,0);
if(s== (char *)-1)
{
std::cout<<"shmat erro"<<std::endl;
exit(1);
}
sem_init();
while(1)
{
char buff[128]={0};
std::cout<<"input "<<std::endl;
fgets(buff,127,stdin);
sem_p(FIR);
strcpy(s,buff);
sem_v(SEC);
if(strncmp(buff,"end",3) ==0)
{
break;
}
}
shmdt(s);
}
结果
ipcs -m:输出所有共享内存(share memory)信息
key:表示共享内存的key
shmid:表示共享内存编号
owner:表示创建共享内存的用户
perms:表示共享内存的的使用权限
bytes:表示共享内存的大小
nattch:表示连接到共享内存的的进程数
status:表示共享的状态(不显示则为正常使用,显示“dest”表示已被标记,但并未真正删除,当这块内存的引用计数为0后则会被删除)
ipcs -lm:输出共享内存(share memory)控制信息