关于共享内存的操作,要用到shmget、shmat、shmctl、shmdt这几个函数,详细说明请大家查看手册
调试的时候可以使用命令ipcs,ipcs -m可以看到共享内存的情况,ipcs -s可以看到信号量的使用情况
以下是我对这几个函数的封装
#ifndef SHAREDMEMORY_H
#define SHAREDMEMORY_H
#include <sys/shm.h>
#define READ_WRITE_FLAG (S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)
class SharedMemory
{
public:
SharedMemory(key_t key,size_t size,const int option);
void* SharedMemoryMat();
void Detach(void* sharedMemory);
void DeleteSharedMemory();
private:
int shmID;
};
#endif
SharedMemory.cpp
#include "SharedMemory.h"
#include "SharedMemoryException.h"
SharedMemory::SharedMemory(key_t key,size_t size,const int option)
{
shmID=shmget(key,size,option);
if(shmID==-1)
throw SharedMemoryException("Failed to get shared memory");
}
void* SharedMemory::SharedMemoryMat()
{
//use (void*)0 to let system select the address of shared memory
void* sharedMemory=shmat(shmID,(void*)0,0);
if(sharedMemory==(void*)-1)
throw SharedMemoryException("Failed in shmat");
return sharedMemory;
}
void SharedMemory::Detach(void* sharedMemory)
{
if(shmdt(sharedMemory)==-1)
throw SharedMemoryException("Failed to delete shared memory");
}
void SharedMemory::DeleteSharedMemory()
{
if(shmctl(shmID,IPC_RMID,0)==-1)
throw SharedMemoryException("Failed to detach shared memory");
}
然后进程之间还要额外进行同步,这里使用信号量进行同步(注意进程同步的信号量与线程的是不一样的)
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
#include <sys/sem.h>
#include <sys/stat.h>
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
#define READ_WRITE_FLAG (S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)
class Semaphore
{
public:
Semaphore(key_t key,int option);
//initialize semaphore
bool SetSemValue(const int value);
bool DeleteSemValue();
bool SemaphoreP();
bool SemaphoreV();
bool SemaphoreOp(const int op);
private:
void SetSemBuf(struct sembuf* semb,const int op);
int semID;
};
#endif
注意union semun可能要自己定义,最好按照手册上的来定义(man semctl)
Semaphore.cpp
View Code
#include "Semaphore.h"
#include "SemaphoreException.h"
#include <stdio.h>
Semaphore::Semaphore(key_t key,int option)
{
semID=semget(key,1,option);
if(semID==-1)
throw SemaphoreException("Failed to create semaphore");
}
//semaphore should be initialized before use
bool Semaphore::SetSemValue(const int value)
{
union semun semUnion;
semUnion.val=value;
if(semctl(semID,0,SETVAL,semUnion)==-1)
{
perror("Failed to initialize semaphore");
return false;
}
return true;
}
bool Semaphore::DeleteSemValue()
{
union semun semUnion;
if(semctl(semID,0,IPC_RMID,semUnion)==-1)
{
perror("Failed to remove the semaphore set");
return false;
}
return true;
}
bool Semaphore::SemaphoreP()
{
return SemaphoreOp(-1);
}
bool Semaphore::SemaphoreV()
{
return SemaphoreOp(1);
}
bool Semaphore::SemaphoreOp(const int op)
{
struct sembuf semb;
SetSemBuf(&semb,op);
if(semop(semID,&semb,1)==-1)
{
perror("Failed in semaphore operation");
return false;
}
return true;
}
void Semaphore::SetSemBuf(struct sembuf* semb,const int op)
{
semb->sem_num=0;
semb->sem_op=op;
semb->sem_flg=SEM_UNDO;
}
接下来我们用共享内存的方式简单解决生产者和消费者问题
生产者
//============================================================================
// Name : sharedMem_Producter.cpp
// Author : Lei
// Version :
// Copyright :
// Description : sharedMem_Producter in C++, Ansi-style
//============================================================================
#include <iostream>
#include "Semaphore.h"
#include "SharedMemory.h"
#include <string.h>
#include <stdlib.h>
using namespace std;
int main()
{
int pauseTime;
void* sharedMemory=static_cast<void*>(0);
//use semaphore to synchronize processes
Semaphore semaphore(static_cast<key_t>(1234),READ_WRITE_FLAG | IPC_CREAT);
semaphore.SetSemValue(1);
//manager shared memory
SharedMemory shManager(static_cast<key_t>(1234),sizeof(char)*1024,READ_WRITE_FLAG | IPC_CREAT);
sharedMemory=shManager.SharedMemoryMat();
bool running=true;
while(running)
{
if(semaphore.SemaphoreP()==false)
running=false;
cout<<"Input your message: ";
char message[1024];
cin>>message;
strcpy(static_cast<char*>(sharedMemory),message);
if(strcmp(static_cast<char*>(sharedMemory),"end")==0)
running=false;
if(semaphore.SemaphoreV()==false)
running=false;
pauseTime=rand()%2;
sleep(pauseTime);
}
//delete shared memory
shManager.DeleteSharedMemory();
//wait for consumer to release semaphore
semaphore.SemaphoreP();
//delete semaphore set
semaphore.DeleteSemValue();
return 0;
}
消费者
View Code
//============================================================================
// Name : sharedMem_Consumer.cpp
// Author : Lei
// Version :
// Copyright :
// Description : sharedMem_Consumer in C++, Ansi-style
//============================================================================
#include <iostream>
#include "Semaphore.h"
#include "SharedMemory.h"
#include <string.h>
#include <stdlib.h>
using namespace std;
int main()
{
int pauseTime;
void* sharedMemory=static_cast<void*>(0);
//use semaphore to synchronize processes
//we had initialized semaphore in producter
//so we don't call Semaphore::SetValue() here
Semaphore semaphore(static_cast<key_t>(1234),READ_WRITE_FLAG);
//manager shared memory
SharedMemory shManager(static_cast<key_t>(1234),sizeof(char)*1024,READ_WRITE_FLAG);
sharedMemory=shManager.SharedMemoryMat();
bool running=true;
while(running)
{
if(semaphore.SemaphoreP()==false)
running=false;
cout<<"Press Y/y to read message from producter: ";
char ch;
cin>>ch;
char message[1024];
strcpy(message,static_cast<char*>(sharedMemory));
cout<<message<<endl;
if(strcmp(static_cast<char*>(sharedMemory),"end")==0)
running=false;
if(semaphore.SemaphoreV()==false)
running=false;
pauseTime=rand()%2;
sleep(pauseTime);
}
shManager.Detach(sharedMemory);
return 0;
}
原文链接: https://www.cnblogs.com/-Lei/archive/2012/09/18/2691719.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/63175
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!