
目录需求1. 代码SharedMem.hppServer.ccClient.ccMakefile2. 控制结果3. 附录3-1 shm_open需求使用进程间互斥锁、条件变量和mmap技术实现通信。控制通信逻辑让目标进程按照我们的需要进行活动。代码为主没有过多的理论这里直接上代码。1. 代码SharedMem.hpp#pragmaonce#includeiostream#includesys/mman.h#includesemaphore.h#includesys/types.h#includesys/stat.h#includefcntl.h#includeunistd.h#includestring.h#includepthread.h#defineSIZE4096classSafeObj{public:SafeObj(){}voidInitObj(){// 初始化锁pthread_mutexattr_t mattr;pthread_mutexattr_init(mattr);pthread_mutexattr_setpshared(mattr,PTHREAD_PROCESS_SHARED);// 设置进程间共享pthread_mutex_init(lock,mattr);// 初始化条件变量pthread_condattr_t cattr;pthread_condattr_init(cattr);pthread_condattr_setpshared(cattr,PTHREAD_PROCESS_SHARED);// 设置进程间共享pthread_cond_init(cond,cattr);// 缓冲区清空memset(buffer,0,sizeof(buffer));}voidCleanupObj(){pthread_mutex_destroy(lock);pthread_cond_destroy(cond);}voidLockObj(){intn::pthread_mutex_lock(lock);(void)n;}voidUnlockObj(){intn::pthread_mutex_unlock(lock);(void)n;}voidWait(){intn::pthread_cond_wait(cond,lock);(void)n;}voidSignal(){intn::pthread_cond_signal(cond);(void)n;}voidBroadCast(){intn::pthread_cond_broadcast(cond);if(n!0)std::cerrbroadcast errorstd::endl;elsestd::cerrbroadcast successstd::endl;}voidGetContent(std::string*out){*outbuffer;}voidSetContent(conststd::stringin){memset(buffer,0,sizeof(buffer));strncpy(buffer,in.c_str(),in.size());}~SafeObj(){}private:pthread_mutex_t lock;pthread_cond_t cond;charbuffer[SIZE];// 未来进程共享的数据区域};// 共享内存对象名必须以 / 开头这是 shm_open 的约定#defineSHARED_MEMORY_FILE/shm#defineSHARED_MEMORY_SIZEsizeof(SafeObj)classMmapMemory{public:MmapMemory(conststd::stringfile,intsize):_file(file),_size(size),_fd(-1),_mmap_addr(nullptr){}voidOpenFile(){_fd::shm_open(_file.c_str(),O_CREAT|O_RDWR,0666);if(_fd0){perror(shm_open);exit(1);}}voidTruncSharedMemory(){intnftruncate(_fd,_size);if(n0){perror(ftruncate);exit(2);}}void*Mmap(){_mmap_addr::mmap(nullptr,_size,PROT_READ|PROT_WRITE,MAP_SHARED,_fd,0);if(_mmap_addrMAP_FAILED){perror(mmap);exit(3);}return_mmap_addr;}voidRemoveFile(){intn::shm_unlink(_file.c_str());if(n0){perror(shm_unlink);exit(4);}}void*MmapAddr(){return_mmap_addr;}~MmapMemory(){if(_fd0){::close(_fd);std::cout关闭mmap文件std::endl;}intn::munmap(_mmap_addr,_size);if(n0){std::coutmunmap 完成std::endl;}}private:int_fd;int_size;std::string _file;void*_mmap_addr;};classMmapMemoryServer:publicMmapMemory{public:MmapMemoryServer():MmapMemory(SHARED_MEMORY_FILE,SHARED_MEMORY_SIZE){MmapMemory::OpenFile();MmapMemory::TruncSharedMemory();MmapMemory::Mmap();objstatic_castSafeObj*(MmapMemory::MmapAddr());obj-InitObj();}// 每个进程都有一次读取数据的机会voidRecvMessage(std::string*out){obj-LockObj();obj-Wait();obj-GetContent(out);obj-UnlockObj();}~MmapMemoryServer(){obj-CleanupObj();MmapMemory::RemoveFile();}private:SafeObj*obj;};classMmapMemoryClient:publicMmapMemory{public:MmapMemoryClient():MmapMemory(SHARED_MEMORY_FILE,SHARED_MEMORY_SIZE){MmapMemory::OpenFile();MmapMemory::Mmap();objstatic_castSafeObj*(MmapMemory::MmapAddr());}voidSendMessage(conststd::stringin){obj-LockObj();obj-SetContent(in);// SafeSharedMemory::Signal(); // 唤醒进程obj-BroadCast();// 把他们全部叫醒让他们自己判断谁应该活动obj-UnlockObj();}~MmapMemoryClient(){}private:SafeObj*obj;};Server.cc#includeSharedMem.hpp#includesys/wait.h#includesys/types.hvoidActive(MmapMemoryServersvr,std::string processname){std::coutprocess is running: processnamestd::endl;std::string who;while(true){svr.RecvMessage(who);if(whoprocessname||whoall){std::coutprocessname is active!std::endl;}if(whoend){std::coutprocessname is quit!std::endl;break;}}}intmain(){MmapMemoryServer svr;for(inti0;i10;i){pid_t idfork();if(id0){std::string nameprocess-std::to_string(i);Active(svr,name);exit(0);}}Active(svr,process-main);for(inti0;i10;i){wait(nullptr);}return0;}Client.cc#includeSharedMem.hpp#includestring.hintmain(){MmapMemoryClient cli;std::string who;while(true){std::coutPlease Enter# ;std::getline(std::cin,who);cli.SendMessage(who);if(whoend){break;}}return0;}Makefile.PHONY:all all:server client server:Server.cc g -o $ $^ -lpthread -lrt -stdc11 -g client:Client.cc g -o $ $^ -lpthread -lrt -stdc11 -g .PHONY:clean clean: rm -f server client2. 控制结果3. 附录3-1 shm_openNAMEshm_open,shm_unlink- create/open or unlink POSIX shared memory objectsSYNOPSIS#includesys/mman.h#includesys/stat.h/* For mode constants */#includefcntl.h/* For O_* constants */intshm_open(constchar*name,intoflag,mode_tmode);intshm_unlink(constchar*name);Link with-lrt.官方说明shm_open()creates and opens a new, or opens an existing, POSIX shared memory object. A POSIX shared memory object is in effect a handle which can be used by unrelated processes tommap(2)the same region of shared memory. Theshm_unlink()function performs the converse operation, removing an object previously created byshm_open().The operation ofshm_open()is analogous to that ofopen(2).namespecifies the shared memory object to be created or opened. For portable use,a shared memory object should be identified by a name of the form /somename; that is, a null-terminated string of up toNAME_MAX(i.e., 255) characters consisting of an initial slash, followed by one or more characters, none of which are slashes.name共享内存对象的名称类似于文件名。这个名称在文件系统中是不可见的它只用于shm_open和其他相关函数来引用共享内存对象。名称必须符合路径名的构造规则。oflag打开标志用于指定打开方式。它可以是以下值的按位或运算组合O_RDONLY以只读方式打开共享内存对象。O_RDWR以读写方式打开共享内存对象。O_CREAT如果共享内存对象不存在则创建它。如果已存在则此标志无效除非与O_EXCL一起使用。O_EXCL与O_CREAT一起使用时如果共享内存对象已存在则shm_open调用失败。O_TRUNC如果共享内存对象存在且以读写方式成功打开则将其截断为零长度。mode权限模式用于指定共享内存对象的权限。这些权限位与创建文件时使用的权限位类似但只考虑低 9 位。