共享内存和信号量的使用

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);
         }
       
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值