system V共享内存shm+ 信号量

#include <stdio.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <error.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
#include "shm.h"

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};

//#define ENABLE_SHM_DEBUG  
#ifdef ENABLE_SHM_DEBUG
     #define YNC_SHM_DEBUG(format,...)    printf("File: "__FILE__", Line: %05d: "format"\n",__LINE__, ##__VA_ARGS__);
#else
     #define YNC_SHM_DEBUG(format,...)
#endif

#define  MAX_TRIES  10

namespace shmaddr
{
	SharedShm::SharedShm(int shmkey,int semkey,int sharesize):
		shm_key(-1),
		sem_key(-1),
		shm_shsize(-1),
		sem_id(-1),
		shm_id(-1),
		shm_addr(NULL)
	{

		Configure(shmkey,semkey,sharesize);
	
	}

	SharedShm::~SharedShm()
	{
		if(shm_addr){
			shm_mdt((void *)shm_addr);
		}
		if(-1 != sem_id){
			del_sem(sem_id);
		}
	}

	int SharedShm::sem_get(int key,int init_value)
	{
		int i;
		union semun sem_union;
		struct semid_ds  seminfo;
		sem_id = semget(key,1,0666 | IPC_CREAT | IPC_EXCL);
		if(errno == EEXIST)  
		{
			if(-1 == (sem_id = semget(key,1,0666 | IPC_CREAT)))
			{
				perror("Get semaphore!\n");
				return -1;
			} else {
				sem_union.buf = &seminfo;
				for(i= 1; i< MAX_TRIES; i++)
				{
					semctl(sem_id,0,IPC_STAT,sem_union);
					if(sem_union.buf->sem_otime == 0)
						usleep(10);
				}
				return 0;
			}
		}

		sem_union.val = init_value;
		if(semctl(sem_id,0,SETVAL,sem_union))
		{
			perror("Initialize semaphore!\n");
			return -1;
		}
		return 0;	
	}

	int SharedShm::sem_P(int sem_id)
	{
		struct sembuf sem_b;
		sem_b.sem_num = 0;
		sem_b.sem_op = -1;
		sem_b.sem_flg = SEM_UNDO;
		YNC_SHM_DEBUG("the sem value is ---before P %d\n",semctl(sem_id,0,GETVAL));
		if(-1 == semop(sem_id,&sem_b,1))
		{
			perror("P operation!\n");
			return -1;
		}		
		YNC_SHM_DEBUG("the sem value is ---after P %d\n",semctl(sem_id,0,GETVAL));
		return 0;
	}
	
	int SharedShm::sem_V(int sem_id)
	{
		struct sembuf sem_b;
		sem_b.sem_num = 0;
		sem_b.sem_op = +1;
		sem_b.sem_flg = SEM_UNDO;				
		YNC_SHM_DEBUG("the sem value is ---before V %d\n",semctl(sem_id,0,GETVAL));
		if(-1 == semop(sem_id,&sem_b,1))
		{
			perror("V operation!\n");
			return -1;
		}
		YNC_SHM_DEBUG("the sem value is ---after V %d\n",semctl(sem_id,0,GETVAL));
		return 0;
	}
	
	int SharedShm::del_sem(int sem_id)
	{
		union semun sem_union;
		if(semctl(sem_id,0,IPC_RMID,sem_union))
		{
			perror("Delete semaphore!\n");
			return -1;
		}
		return 0;
	}
	
	int SharedShm::shm_get(int key,int sharesize)
	{
		shm_key = key;
		shm_shsize = sharesize;
		if(-1 == (shm_id = shmget(shm_key,shm_shsize,0666|IPC_CREAT)))
		{
			perror("Get share memory!\n");
			return -1;
		}
		return 0;
	}
	
	int SharedShm::shm_mat(int shm_id,void* shmaddr)
	{
		if((void*)-1 == shmat(shm_id,shmaddr,0))
		{
			perror("Shmat share memory!\n");
			return -1;
		}
		shm_addr = (char*)shmat(shm_id,shmaddr,0);
		return 0;
	}
	
	int SharedShm::shm_mdt(void* shmaddr)
	{
		if(-1 == shmdt(shmaddr))
		{
			perror("Shmdt share memory!\n");
			return -1;	
		}
		return 0;
	}
	
	int SharedShm::Configure(int shmkey,int semkey,int sharesize)
	{
		shm_get(shmkey,sharesize);
		shm_mat(shm_id,NULL);
		sem_get(semkey,1);
		return 0;
	}
		
	int SharedShm::Read(char* dst,int offset,int len)
	{
		if(NULL == dst)
		{
			printf("dst addres is null,please request correct address!\n");
			return -1;
		}
		if((offset + len) > shm_shsize)
		{
			printf("the request data beyond the share memory size!\n");
			return -1;
		}
		if(-1 == shm_id)
		{
			printf("bad share memory file destriptor!\n");
			return -1;
		}
		if(!sem_P(sem_id))
		{
			memcpy(dst,shm_addr+offset,len);
			return sem_V(sem_id);
		}
		return -1;
	}
	
	int SharedShm::Write(char* src,int offset,int len)
	{
		if(NULL == src)
		{
			printf("src addres is null,please request correct address!\n");
			return -1;			
		}
		if((offset + len) > shm_shsize)
		{
			printf("the request data beyond the share memory size!\n");
			return -1;			
		}
		if(NULL == shm_addr)
		{
			printf("share memory address is null!\n");
			return -1;
		}
		if(-1 == shm_id)
		{
			printf("bad share memory file destriptor!\n");
			return -1;					
		}
		if(!sem_P(sem_id))
		{
			memcpy(shm_addr+offset,src,len);
			return sem_V(sem_id);
		}
		return -1;			
	}	
}

shm.h

#include <stdlib.h>
#include <stdio.h>

namespace shmaddr
{
	class SharedShm
	{
	public:
		SharedShm(int shmkey,int semkey,int sharesize);
		~SharedShm();
		int Read(char *dst,int offset,int len);
		int Write(char *src,int offset,int len);
	private:
		int  shm_key;
		int  sem_key;
		int  shm_shsize;
		int  sem_id;
		int  shm_id;
		char* shm_addr;
		int Configure(int shmkey,int semkey,int sharesize);
		int sem_get(int key,int sharesize);
		int sem_init(int init_value);
		int sem_P(int sem_id);
		int sem_V(int sem_id);
		int del_sem(int sem_id);
		int shm_get(int key,int sharesize);
		int shm_mat(int shm_id,void* shmaddr);
		int shm_mdt(void* shmaddr);
	};
}

发布了95 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ding283595861/article/details/105286176