共享内存
创建共享内存
key_t ftok(const char *pathname, int proj_id);
使用相同的pathname和proj_id可以得到相同的key_t
pathname必须是一个存在的目录
int shmget(key_t key, size_t size, int shmflg);
需要使用ftok获取key_t
IPC_CREAT——不存在就创建,存在就获取
IPC_EXCL——一般和IPC_CREAT组合使用。不存在创建,存在错误返回;保证了共享内存是最新的
size
最好是4096
的整数倍
错误代码
int shmid=shmget(key,4096,IPC_CREAT);
int shmid=shmget(key,4096,IPC_CREAT|0644);
创建共享内存也是需要权限的,如果不给权限,能创建出来,但是在链接的时候会失败
挂接
void *shmat(int shmid, const void *shmaddr, int shmflg);
// char* shm_block =(char*)shmat(shmid,nullptr,0);
// if(*(int*)shm_block==-1)
// {
// puts("不接受链接");
// exit(-1);
// }
// puts("链接共享内存");
标识将shmid进行挂接,
挂接位置,挂接方式为默认
解除挂接
int shmdt(const void *shmaddr);
删除共享内存
一共有3种选项,这里就说两种方法
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmctl(shmid, IPC_RMID, nullptr);
删除不需要属性
获取属性
struct shmid_ds ds;
shmctl(shmid,IPC_STAT,&ds);
std::cout<<ToHex(ds.shm_perm.__key)<<std::endl; // key
获取属性需要在
创建成功之后和释放成功之前
获取
删除
- key:表示共享内存的key
- shmid:表示共享内存编号
- owner:表示创建共享内存的用户
- perms:表示共享内存的的使用权限
- bytes:表示共享内存的大小
- nattch:表示连接到共享内存的的进程数
- status:表示共享的状态(不显示则为正常使用,显示“dest”表示共享内存已被删除,但仍有用户使用)
ipcs -m
查看所有共享内存
ipcrm -m shmid
=unlink + 管道名
key 旨在内核中标识shm的唯一性
shmid 用户使用;类似于fd(编号)
注意
共享内存不提供同步机制,需要控制控制同步——管道
通过管道控制同步
#include<iostream>
using namespace std;
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
const char* pathname="/home/yao/test/test1/shm";
const char* filename="/home/yao/test/test1/shm/tem.txt";
const int proj_id=0x3f3f3f3f;
int main()
{
// 需要一个存在的文件或者目录
key_t key=ftok(pathname,proj_id);
if(key==-1)
{
perror("ftok failure:>");
exit(-1);
}
int shmid=shmget(key,4096,IPC_CREAT);
if(shmid==-1)
{
perror("shmget failure:>");
exit(-1);
}
char* ret=(char*)shmat(shmid,nullptr,0);
if(*(int*)ret==-1)
{
perror("shmat failure:>");
exit(-1);
}
// 写入并控制
// 控制应该是管道,但是一个普通的文件不能当成管道
// 需要一个有名管道
int fd=open(filename,O_WRONLY); // 需要一个已经存在的文件或者目录
if(fd==-1)
{
perror("open failure:>");
exit(-1);
}
int cnt=0;
for(int i=0;i<=32;i++)
{
int code=0;
ssize_t t=write(fd,&code,sizeof(code));
ret[i]='a'+i;
ret[i+1]=0;
sleep(2);
}
shmdt(ret);
return 0;
}
#include<iostream>
using namespace std;
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
const char* pathname="/home/yao/test/test1/shm";
const char* filename="/home/yao/test/test1/shm/tem.txt";
const int proj_id=0x3f3f3f3f;
int main()
{
key_t key=ftok(pathname,proj_id);
if(key==-1)
{
perror("ftok failure:>");
exit(-1);
}
int shmid=shmget(key,4096,IPC_CREAT|0666);
if(shmid==-1)
{
perror("shmget failure:>");
exit(-1);
}
char* ret=(char*)shmat(shmid,nullptr,0);
if(*(int*)ret==-1)
{
perror("shmat failure:>");
exit(-1);
}
mkfifo(filename,0666);
int fd=open(filename,O_RDONLY);
if(fd==-1)
{
perror("open failure:>");
exit(-1);
}
for(int i=0;i<=33;i++)
{
int code=0;
ssize_t t = read(fd,&code,sizeof(code));
// if(t==0)
// {
// puts("写端关闭");
// break;
// }
cout<<"读取字符串 "<< ret <<endl;
sleep(1);
}
shmdt(ret);
shmctl(shmid,IPC_RMID,nullptr);
remove(filename);
return 0;
}
- server两秒写一个,client是每秒度一个,但是client需要等server1秒,这就是
同步机制
- 同时验证了内存是
拷贝出去
的,并不会清空
system_v参考