C++ Linux IPC进程通信-共享内存
共享内存<sys/shm.h>
库函数
// 创建共享内存
int shmget(key_t key, size_t size, int shmflg);
return 共享内存的ID(成功) -1(错误)
key为一个标记内存的关键字,可用自己指定,也可以用ftok函数转文件名为key,
shmflg标志包括IPC_CREAT(创建)|IPC_EXCL(存在则报错)|SHM_RDONLY(只读)|SHM_RND(附加到指定地址的最接近的可用地址)|SHM_NORESERVE(不预留共享内存资源)
!!:注意IPC命名对象需要指定该对象的文件权限如IPC_CREAT|0666
// 分配空间并连接
void *shmat(int shm_id, const void *shm_addr, int shmflg);
return 分配空间首地址 或 -1
shm_id为返回的id shm_addr为nullptr自动分配,否则就近分配 shmflg可为SHM_RDONLY(只读)|SHM_NORESERVE(不预留共享内存资源)
// 删除连接(不删除空间)
int shmdt(const void *shmaddr); shmaddr为首地址
return 成功0,出错-1
//控制
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
return 成功0,出错-1
cmd:IPC_STAT(读出数据到buf),IPC_SET(写入),IPC_RMID(删除共享内存)
该控制命令实际上就是通过更新结构体来控制共享内存配置,如分配大小或其他的
struct shmid_ds {
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
//其他配置
};
使用memcpy实现数据的移动
实例:使用信号量+共享内存实现变量自增
#include <iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <semaphore.h>
#include <unistd.h>
#include <string.h>
using namespace std;
class Cnt{
public:
int c; //需要共享
string s; //不需要共享
Cnt():c(0),s(""){};
~Cnt(){};
};
template <typename T>
void check(const char* er, const T& a, const T& b) {
if (a == b) {
perror(er);
exit(EXIT_FAILURE);
}
}
void run(Cnt &cnt,sem_t *nsem,void *addr,int size){
for(int i=0;i<3;i++){
sem_wait(nsem);
memcpy(&(cnt.c),addr,size);
cnt.c++;
cout<<cnt.c<<"\n";
memcpy(addr,&(cnt.c),size);
sem_post(nsem);
}
}
int main()
{
Cnt cnt;
int size= sizeof(cnt.c);
sem_t* nsem=sem_open("name_sem",O_CREAT,0666,1);
check(string("sem_open").c_str(),nsem,SEM_FAILED);
int fd=open("./shm",O_CREAT|O_RDWR,0666);
check(string("open").c_str(),fd,-1);
check(string("close").c_str(),close(fd),-1);
key_t k=ftok("./shm",'A');
check(string("ftok").c_str(),k,-1);
int sid=shmget(k,size,IPC_CREAT|0666);
check(string("shmget").c_str(),sid,-1);
void *addr = shmat(sid,nullptr,0);
check(string("shmat").c_str(),addr,(void*)-1);
pid_t cid=fork();
if(cid==-1){
perror("fork");
exit(EXIT_FAILURE);
}else if(cid>0){
run(cnt,nsem,addr,size);
}else{
run(cnt,nsem,addr,size);
}
if(cid>0){
check(string("shmdt").c_str(),shmdt(addr),-1);
check(string("shmctl").c_str(),shmctl(sid,IPC_RMID,nullptr),-1);
check(string("sem_close").c_str(),sem_close(nsem),-1);
check(string("sem_unlink").c_str(),sem_unlink("name_sem"),-1);
}
return 0;
}
特点
优点
优点速度快,大量数据操作下效率高,直接对内存操作.
缺点
需要其他的方法实现同步支持,并且对内存管理和分配有要求
原文地址:https://blog.csdn.net/qq_58539881/article/details/142317256
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!