linux共享内存共享消息队列
初衷
又想使用共享内存的高效,又想使用队列来让两个进程进行异步通信。
用到的系统调用
1. ftok
每个共享内存都要有一个对应的key相关联
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
//path为要共享的路径
//id为0-255之间的整数,自己取
//成功返回key,失败返回-1
2. shmget
创建共享段并返回一个共享段的标识符
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t, size_t size, int shmflg);
//Key 为ftok生成的key
//size为共享内存的大小
//shmflg标志代表所需要的操作和权限
// IPC_CREAT 创建一个新的段,如果没用这个flg,他就会找和key关联的段,并检查你有没有对应权限
// IPC_EXCL 该flg和IPC_CREAT一起使用以确保创建了段,如果对应的段已经存在了,则会调用失败
//
// 返回共享内存段的标识符,失败返回-1
//基本会使用上面两个,剩余可去问男人(man)
3. shmat
获取共享段地址
#include<sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
//shmid为shmget返回的id
//shaddr为制定共享内存出现在进程内存地址的什么位置,如果为NULL,系统将选择一个合适(未使用的)的页面地址来将共享内存段和进程内存对齐,如果不为NULL,并且在shmflg设置了SHM_RND,他会将共享内存段和SHMLBA对齐(SHMLBA问男人)
//shmflg为对数据的操作,如果指定SHM_RDONLY则以制度方式连接共享段,其他值为rw方式连接该内存段。
//返回值:成功返回指向共享存储段的指针;错误返回-1
4. shmdt
当不需要对共享段操作的时候,可以用它来分离(不是删除共享段
#include<sys/shm.h>
int shmdt(const void *shmaddr);
//shmaddr为shmat返回的地址指针
//成功返回0,错误-1
5. shmctl
对共享段进行控制,比如删除它
#include<sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//shmid为shmget返回的标识符
//cmd代表你要做的操作,
// 删除是IPC_RMID
// IPC_STAT 得到共享段的状态
// IPC_SET 改变共享段的状态 将buf所指的一些成员数据写入内核为共享内存维护的一个buf里
//成功返回0,失败-1
demo
通过共享内存在两个进程中使用同一个struct,可以在struct封装链表/队列等,这里懒就没写
还有原谅我有的地方不加错误判断和在C++里面写C
//wirte.cpp 进行写操作
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#include <unistd.h>
#include <iostream>
#include <cstdio>
struct data {
int pos;
char name[8];
};
int main() {
key_t key = ftok("./", 123);
int id = shmget(key, 1024*5, IPC_CREAT|0666);
if(id == -1) {
std::cout << "faild" << std::endl;
exit(-1);
}
else std::cout << "shmget success" << std::endl;
data *pmap;
pmap = (data *)shmat(id, 0, 0);
pmap->pos = 888;
strncpy(pmap->name, "liar", 4);
std::cout << "write success" << std::endl;
sleep(10);
shmdt(pmap);
shmctl(id, IPC_RMID, 0);
return 0;
}
//read.cpp 进行读操作;
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#include <unistd.h>
#include <iostream>
#include <cstdio>
struct data {
int pos;
char name[8];
};
int main() {
key_t key = ftok("./", 123);
int id = shmget(key, 1024*5, 0);
data *pmap;
pmap = (data *)shmat(id, 0, 0);
std::cout << "name is :" << pmap->name << std::endl;
std::cout << "pos is :" << pmap->pos << std::endl;
shmdt(pmap);
return 0;
}
查看IPC
ipcs -m #查看ipc
ipcrm -m id #删除ipc