共享内存做进程间消息队列

来源:互联网 发布:数据科学与大数据技术 编辑:程序博客网 时间:2024/05/16 10:12




sharemem.h

#ifndef _SHAREMEM_H_#define _SHAREMEM_H_#include <stdio.h>#include <stdlib.h>#include <unistd.h>   #include <fcntl.h>   #include <string.h>#include <fcntl.h>#include <iostream>#include <pthread.h>#include <errno.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#include <sys/stat.h>#define SHMKEY (key_t) 0x100 #define SEMKEY (key_t) 0x200 #define IFLAGS (IPC_CREAT|IPC_EXCL) #define ERR ((void*) -1)#define MSG_HEADER_SIZE 8int64_t g_count = 100;//for shm#define SHM_SIZE 50//1048576 //1024 * 1024char* g_share_mem_ptr = NULL;   //取得共享内存的指针int g_shmid = -1;bool g_have_shm;//for mutex#define WRITE_INDEX_POSITION 0#define READ_INDEX_POSITION  8#define DATA_INDEX_POSITION  16#define SHM_DATA_SIZE 34//SHM_SIZE - DATA_INDEX_POSITION#define POSITION_SIZE        8int64_t g_write_offest; int64_t g_read_offest;//for sem#define SEM_OP_MAX 2 //#define SEM_OP_MIN 0int g_semid = -1;union semun{int val; //信号量初始值                   struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;};//sops:指向存储信号操作结构的数组指针,信号操作结构的原型如下//struct sembuf//{//unsigned short sem_num; /* semaphore number *///short sem_op; /* semaphore operation *///short sem_flg; /* operation flags *///};//sem_num:操作信号在信号集中的编号,第一个信号的编号是0。//sem_op://如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;//如果为负数,而其绝对值又大于信号的现值,操作将会阻塞,//直到信号值大于或等于sem_op的绝对值。//通常用于获取资源的使用权;//如果sem_op的值为0,如果没有设置IPC_NOWAIT,//则调用该操作的进程或者线程将暂时睡眠,直到信号量的值为0;//否则,进程或者线程不会睡眠,函数返回错误EAGAIN。//sem_flg:信号操作标志,可能的选择有两种//IPC_NOWAIT //对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。//SEM_UNDO //程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。//这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。struct sembuf p0 = { 0, -1, 0},    //本组第1个信号量,阻塞加1,p1 = { 1, -1, 0},    //本组第2个信号量,阻塞加1,v0 = { 0, 1, 0},     //本组第1个信号量,放开加1,v1 = { 1, 1, 0};     //本组第2个信号量,放开加1,#pragma  pack(push)  //让原字节对齐方式入编译器栈#pragma  pack(1)    //指定新的对齐方式, 1字节对齐.  (数字即几字节对齐)struct DataUnit {int32_t type_;int32_t size_;char* data_ptr_;int32_t AppendTo(const char* dist_str){std::string data;data.append(data_ptr_, size_);std::cout << type_ << "\t"<< size_ << "\t"<< data << std::endl;memcpy((void*)dist_str,       (void*)&type_,    4);memcpy((void*)(dist_str + 4), (void*)&size_,    4);memcpy((void*)(dist_str + MSG_HEADER_SIZE), (void*)data_ptr_, size_);//memcpy((void*)dist_str, (void*)this, sizeof(DataUnit));return 0;}int32_t GetSize(){return 8 + size_;}static void Output(const char* str){DataUnit unit;memcpy((void*)(&unit.type_), (void*)str , 4);memcpy((void*)(&unit.size_), (void*)(str + 4), 4);std::string data;data.append(str + MSG_HEADER_SIZE, unit.size_);std::cout << unit.type_ << "\t"<< unit.size_ << "\t"<< data << std::endl;}static int32_t GetCurrentSize(const char* str){int32_t size = 0;memcpy((void*)(&size), (void*)(str + 4), 4);return MSG_HEADER_SIZE + size;}};#pragma pack(pop)//出栈原来对齐方式inline void pr_error(const char *mess){perror(mess);//exit(1);}inline bool GetShareMem(){/*取得共享内存的key,如果还没建立的话,就建立(IPC_CREAT)*/if ((g_shmid = shmget(SHMKEY, SHM_SIZE, 0600 | IFLAGS)) < 0){if (errno == EEXIST){g_have_shm = true;g_shmid = shmget(SHMKEY, SHM_SIZE, 0600 | IPC_CREAT);if (g_shmid < 0){pr_error("shmget");}}else{pr_error("shmget");}}else{g_have_shm = false;}g_write_offest = 0;g_read_offest = 0;void* shm_ptr = NULL;/*取得共享内存的指针,使用共享内存时可以和malloc分配的内存一样*/if ((shm_ptr = (shmat(g_shmid, 0, 0))) == ERR){pr_error("shmat");}g_share_mem_ptr = (char*)shm_ptr;if (g_have_shm){memcpy((void*)&g_write_offest, (void*)(g_share_mem_ptr + WRITE_INDEX_POSITION), POSITION_SIZE);memcpy((void*)&g_read_offest, (void*)(g_share_mem_ptr + READ_INDEX_POSITION), POSITION_SIZE);}}inline void GetSem(int& semid){ /*建立信号量(且称为A和B)*/if ((semid = semget(SEMKEY, 2, 0600 | IFLAGS)) < 0){if (errno == EEXIST){semid = semget(SEMKEY, 2, 0600 | IPC_CREAT);if (semid < 0){pr_error("semget");}else{/*加上这一句,如果已存在,不再初始化信号量*/return;}}else{pr_error("semget");}}/*设置信号量A初值为0*///semctl()的第一个参数是信号量集IPC标识符。//第二个参数是操作信号在信号集中的编号,第一个信号的编号是0。union semun init_min, init_max;init_min.val = SEM_OP_MIN;init_max.val = SEM_OP_MAX;if (semctl(semid, 0, SETVAL, init_min) < 0){pr_error("semctl");}/*设置信号量B初值为1*/if (semctl(semid, 1, SETVAL, init_max) < 0){pr_error("semctl");}//std::cout << semctl(semid, 0, GETVAL, 0) << "\t" << semctl(semid, 1, GETVAL, 0) << std::endl;}//互斥锁位于共享内存区,将用于不同进程之间的上锁,设置互斥锁的属性为PTHREAD_PROCESS_SHARED,并初始化互斥锁。inline void my_lock_init(pthread_mutex_t*& mptr){int fd;pthread_mutexattr_t mattr;fd = open("/dev/zero", O_RDWR, 0);mptr = (pthread_mutex_t*)mmap(0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);close(fd);pthread_mutexattr_init(&mattr);pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);pthread_mutex_init(mptr, &mattr);}//上锁inline void my_lock_wait(pthread_mutex_t* mptr){pthread_mutex_lock(mptr);}//解锁inline void my_lock_release(pthread_mutex_t* mptr){pthread_mutex_unlock(mptr);}inline void RemoveIPC(){if (!g_have_shm){/*删除共享内存*/if (g_shmid > 0 && shmctl(g_shmid, IPC_RMID, 0) < 0)pr_error("shmctl");}}#endif


systemv_produce.c

#include "../sharemem.h"pthread_mutex_t* mptr;void Writer(){//for data create startsrand((unsigned)time(NULL));char buf_data[256];memset(buf_data, 0, 256);memcpy(buf_data, "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", 90);std::cout << buf_data << std::endl;DataUnit buf;buf.data_ptr_ = &buf_data[0];//for data create endif (g_have_shm){pthread_mutex_lock(mptr);memcpy((void*)&g_write_offest, (void*)(g_share_mem_ptr + WRITE_INDEX_POSITION), POSITION_SIZE);memcpy((void*)&g_read_offest, (void*)(g_share_mem_ptr + READ_INDEX_POSITION), POSITION_SIZE);pthread_mutex_unlock(mptr);}int64_t realy_write_offset = 0;int64_t realy_read_offset = 0;int64_t all_space = 0;int64_t head_space = 0; int64_t tail_space = 0;char current_buf_data[256];for (int i = 0; i < g_count; i++){//for data create startbuf.type_ = rand() % 10 + 1;buf.size_ = rand() % 20 + 1;//for data create endbuf.AppendTo(current_buf_data);   //写共享内存all_space = SHM_DATA_SIZE - g_write_offest + g_read_offest;while (all_space < buf.GetSize()){sleep(1);memcpy((void*)&g_read_offest, (void*)(g_share_mem_ptr + READ_INDEX_POSITION), POSITION_SIZE);all_space = SHM_DATA_SIZE - g_write_offest + g_read_offest;}realy_write_offset = g_write_offest % SHM_DATA_SIZE;realy_read_offset  = g_read_offest  % SHM_DATA_SIZE;if (realy_write_offset >= realy_read_offset){head_space = realy_read_offset;tail_space = all_space - head_space;} else{head_space = 0;tail_space = all_space - head_space;}//std::cout << "all_space: "<< all_space << "\thead_space: " << head_space << "\t tail_space: " << tail_space << std::endl;;pthread_mutex_lock(mptr);if (tail_space > buf.GetSize()){memcpy((void*)(g_share_mem_ptr + DATA_INDEX_POSITION + realy_write_offset), (void*)current_buf_data, buf.GetSize());std::cout << "start: " << DATA_INDEX_POSITION + realy_write_offset << "\t size: " << buf.GetSize() << std::endl;;}else{memcpy((void*)(g_share_mem_ptr + DATA_INDEX_POSITION + realy_write_offset), (void*)current_buf_data, tail_space);memcpy((void*)(g_share_mem_ptr + DATA_INDEX_POSITION), (void*)(current_buf_data + tail_space), buf.GetSize() - tail_space);std::cout << "start: " << DATA_INDEX_POSITION + realy_write_offset << "\t tail_space: " << tail_space << std::endl;;std::cout << "start: " << DATA_INDEX_POSITION << "\t tail_space: " << buf.GetSize() - tail_space << std::endl;;}g_write_offest += buf.GetSize();memcpy((void*)(g_share_mem_ptr + WRITE_INDEX_POSITION), (void*)&g_write_offest, POSITION_SIZE);pthread_mutex_unlock(mptr);std::cout << g_write_offest << std::endl;sleep(1);}return;}main(){//GetSem(semid);my_lock_init(mptr);GetShareMem();Writer();RemoveIPC();exit(0);}


systemv_consumer.c

#include "../sharemem.h"pthread_mutex_t* mptr;void Reader(){if (g_have_shm){pthread_mutex_lock(mptr);memcpy((void*)&g_write_offest, (void*)(g_share_mem_ptr + WRITE_INDEX_POSITION), POSITION_SIZE);memcpy((void*)&g_read_offest, (void*)(g_share_mem_ptr + READ_INDEX_POSITION), POSITION_SIZE);pthread_mutex_unlock(mptr);}int32_t current_msg_size = 0;int64_t realy_write_offset = 0;int64_t realy_read_offset = 0;int64_t all_space = 0;int64_t head_space = 0;int64_t tail_space = 0;char current_buf_data[256];for (int i = 0; i < g_count; i++){std::cout << g_write_offest << "\t" << g_read_offest << std::endl;;if (g_write_offest > g_read_offest){realy_write_offset = g_write_offest % SHM_DATA_SIZE;realy_read_offset = g_read_offest % SHM_DATA_SIZE;if (realy_write_offset > realy_read_offset){head_space = 0;tail_space = realy_write_offset - realy_read_offset;}else{head_space = realy_write_offset;tail_space = SHM_DATA_SIZE - realy_read_offset;}//获取消息长度if (tail_space >= MSG_HEADER_SIZE){current_msg_size = DataUnit::GetCurrentSize((char*)g_share_mem_ptr + DATA_INDEX_POSITION + realy_read_offset);} else{memcpy(current_buf_data, (char*)g_share_mem_ptr + DATA_INDEX_POSITION + realy_read_offset, tail_space);memcpy(current_buf_data + tail_space, (char*)g_share_mem_ptr + DATA_INDEX_POSITION, DATA_INDEX_POSITION - tail_space);current_msg_size = DataUnit::GetCurrentSize(current_buf_data);}//获取消息if (tail_space >= current_msg_size){DataUnit::Output((char*)g_share_mem_ptr + DATA_INDEX_POSITION + realy_read_offset);std::cout << "start: " << DATA_INDEX_POSITION + realy_read_offset << "\t size: " << current_msg_size << std::endl;;}else{memcpy(current_buf_data, (char*)g_share_mem_ptr + DATA_INDEX_POSITION + realy_read_offset, tail_space);memcpy(current_buf_data + tail_space, (char*)g_share_mem_ptr + DATA_INDEX_POSITION, current_msg_size - tail_space);DataUnit::Output(current_buf_data);std::cout << "start: " << DATA_INDEX_POSITION + realy_read_offset << "\t tail_space: " << tail_space << "\t head_space: " << current_msg_size - tail_space << std::endl;;}g_read_offest += current_msg_size;if (g_write_offest <= g_read_offest){pthread_mutex_lock(mptr);memcpy((void*)(g_share_mem_ptr + READ_INDEX_POSITION), (void*)&g_read_offest, POSITION_SIZE);pthread_mutex_unlock(mptr);}else{continue;}}else{usleep(1000000);}pthread_mutex_lock(mptr);memcpy((void*)&g_write_offest, (void*)(g_share_mem_ptr + WRITE_INDEX_POSITION), POSITION_SIZE);pthread_mutex_unlock(mptr);}return;}main(){my_lock_init(mptr);GetShareMem();Reader();RemoveIPC();exit(0);}



0 0
原创粉丝点击