Linux 编程 共享内存
关于共享内存的操作,要用到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; }



浙公网安备 33010602011771号