1.共享内存
1.1共享内存介绍
共享内存是常用的进程间通信方式,速度最快,对系统资源占用最少
1.2常用接口
1)shmget
创建共享内存
int shmget(key_t key, size_t size, int shmflg);
key:共享内存的名字
size:共享内存的大小
返回值:失败返回-1
2) shmat
将共享内存连接到进程空间
void* shmat(int shm_id, const void *shm_addr, int shmflg);
shm_id: shmget返回的id
shm_addr: 通常为NULL
shmflag: 操作类型和访问权限
返回值: 失败返回-1;成功返回共享内存的第一个指针
3)shmdt
shmdt的作用是将共享内存从当前进程分离,从共享内存分离并未删除它,只是使得该共享内存对当前进程不可用。
2.信号量
2.1信号量介绍
信号量用于进程间通讯的互斥
2.2 常用接口
1)semget
创建信号量
int semget(key_t key, int nsems, int semflg)
key:信号量键值
nsems:创建信号量的个数
semflg:操作类型和访问权限
返回值:
Demo
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <sys/sem.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
class ShmDemo {
public:
ShmDemo(int key, uint32_t size);
~ShmDemo();
int ShmWrite(uint8_t *buf, int len);
int ShmRead(uint8_t *buf, int offset, int len);
private:
int SemP();
int SemV();
int SemInit();
private:
key_t shmKey_;
uint32_t shmSize_;
int shmId_ = -1;
int semId_ = -1;
uint8_t *shmPtr_ = nullptr;
};
ShmDemo::ShmDemo(int key, uint32_t size)
{
shmKey_ = key;
shmSize_ = size;
int shmId_ = shmget(shmKey_, shmSize_, 0666 | IPC_CREAT);
if( shmId_ < 0 ) {
printf(" shm get error:%s\n", strerror(errno));
return;
}
void *shmAttachRet = shmat(shmId_, NULL, 0);
if( shmAttachRet == (void *)-1) {
printf("shm attach error:%s\n", strerror(errno));
return;
}
shmPtr_ = (uint8_t *)shmAttachRet;
semId_ = semget(shmKey_, 1, 0666 | IPC_CREAT);
SemInit();
}
int ShmDemo::SemP()
{
// 申请信号
sembuf semP;
semP.sem_num = 0;
semP.sem_op = -1;
semP.sem_flg = SEM_UNDO;
semop(shmId_, &semP, 1);
return 0;
}
int ShmDemo::SemV()
{
sembuf semV;
semV.sem_num = 0;
semV.sem_op = 1;
semV.sem_flg = SEM_UNDO;
semop(shmId_, &semV, 1);
return 0;
}
union SemUnion {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int ShmDemo::SemInit()
{
union SemUnion semUnion;
semUnion.val = 1;
if (semctl(semId_, 0, SETVAL, semUnion) < 0) {
printf("sem ctl error:%s\n", strerror(errno));
return -1;
} else {
return 0;
}
}
int ShmDemo::ShmWrite(uint8_t *buf, int len)
{
SemP();
int writeLen = len;
if(shmPtr_ == nullptr) {
printf("write shm address :attached address is null\n");
return -1;
}
if (len > shmSize_) {
printf("write len over %d, cunt off", shmSize_);
writeLen = shmSize_;
}
memcpy(shmPtr_, buf, writeLen);
SemV();
return writeLen;
}
int ShmDemo::ShmRead(uint8_t * buffer, int offset, int len)
{
SemP();
int writeLen = 0;
if(shmPtr_ == nullptr) {
printf("read shm attached address is null\n");
return -1;
}
if(offset + len > shmSize_) {
printf("read over max shm size");
return -1;
}
memcpy(buffer, shmPtr_ + offset, len);
SemV();
return len;
}
#define SHMDEMO_KEY 101
#define SHMDEMO_SIZE 1024
int main(int argc, char* argv[])
{
if(argc < 2) {
printf("argument num is need 2 at least!");
return -1;
}
if(argv[1][0] == 'w') {
ShmDemo *demoShmWrite = new ShmDemo(SHMDEMO_KEY, SHMDEMO_SIZE);
while (true)
{
char writeBuf[1024] = {0};
fgets(writeBuf, sizeof(writeBuf), stdin);
printf("write data:%s\n", writeBuf);
demoShmWrite->ShmWrite((uint8_t*)writeBuf, sizeof(writeBuf));
sleep(1);
}
} else if(argv[1][0] == 'r') {
ShmDemo *demoShmRead = new ShmDemo(SHMDEMO_KEY , SHMDEMO_SIZE);
while(true) {
uint8_t readBuf[100] = {0};
demoShmRead->ShmRead(readBuf, 0, 20);
printf("read data:%s\n", readBuf);
sleep(1);
}
}
}