内存共享是进程间常用的通信方式,可以实现两个完全独立的进程通信。
在访问共享内存时,同时需要信号量进行访问控制。
使用ipcs -m命令可以查看系统共享内存,ipce -m + key 可以删除指定的共享内存。
对共享内存操作时,使用信号量对共享内存进行保护,类似与线程中的互斥锁。都可以看做是通过PV操作实现临界资源保护。
P:对信号量标记位-1,获取信号量,如果标记位为0,表示有其他进程占用资源,无法获取。
V:对信号量标记位+1,释放信号量,将资源释放,给其他进程使用。
信号量和内存共享需要使用到的函数类似,下面是具体代码实现,函数参数不具体介绍。
1 //shmwrite.cpp 2 #include <sys/types.h> 3 #include <sys/sem.h> 4 #include <sys/shm.h> 5 #include <string.h> 6 #include <iostream> 7 8 using namespace std; 9 10 const int SEMTAG = 0x2456; 11 const int SHMTAG = 0x3443; 12 const int MAXBUFFLEN = 1024; 13 14 class SemOp 15 { 16 public: 17 SemOp():m_iSemID(0){}; 18 void InitSem(); 19 void GetSem(); 20 void ReleaseSem(); 21 void DelSem(); 22 private: 23 int m_iSemID; 24 }; 25 26 class ShmOp 27 { 28 public: 29 ShmOp():m_iShmID(0){}; 30 void InitShm(); 31 void WriteShm(); 32 void ReadShm(); 33 void DelShm(); 34 private: 35 int m_iShmID; 36 void *m_memAddr; 37 }; 38 39 void SemOp::InitSem() 40 { 41 if ((m_iSemID = semget(SEMTAG, 1, 0600|IPC_CREAT)) <= 0) 42 cout<<"get semID failure!"<<endl; 43 semctl(m_iSemID, 0, SETVAL, 1); 44 } 45 void SemOp::GetSem() 46 { 47 struct sembuf sem_get; 48 sem_get.sem_num = 0; 49 sem_get.sem_op = -1; 50 sem_get.sem_flg = SEM_UNDO; 51 semop(m_iSemID,&sem_get,1); 52 } 53 void SemOp::ReleaseSem() 54 { 55 struct sembuf sem_release; 56 sem_release.sem_num = 0; 57 sem_release.sem_op = 1; 58 sem_release.sem_flg = SEM_UNDO; 59 semop(m_iSemID,&sem_release,1); 60 } 61 void SemOp::DelSem() 62 { 63 semctl(m_iSemID, 0, IPC_RMID); 64 } 65 66 void ShmOp::InitShm() 67 { 68 if ((m_iShmID = shmget(SHMTAG, MAXBUFFLEN, 0600|IPC_CREAT)) <= 0) 69 cout<<"get m_iShmID failure!"<<m_iShmID<<endl; 70 } 71 void ShmOp::WriteShm() 72 { 73 char buff[MAXBUFFLEN]; 74 cin>>buff; 75 m_memAddr = reinterpret_cast<void *>(shmat( m_iShmID, NULL, 0 )); 76 memcpy(m_memAddr,buff,sizeof(buff)); 77 78 } 79 void ShmOp::ReadShm() 80 { 81 char buff[MAXBUFFLEN]; 82 m_memAddr = reinterpret_cast<void *>(shmat( m_iShmID, NULL, 0 )); 83 memcpy(buff,m_memAddr,sizeof(buff)); 84 cout<<buff; 85 } 86 void ShmOp::DelShm() 87 { 88 shmdt(m_memAddr); 89 } 90 91 int main() 92 { 93 SemOp sem; 94 ShmOp shm; 95 96 sem.InitSem(); 97 shm.InitShm(); 98 99 sem.GetSem(); 100 shm.WriteShm(); 101 sem.ReleaseSem(); 102 103 shm.DelShm(); 104 sem.DelSem(); 105 return 0; 106 }读共享内存代码类似,只需要修改main函数,对共享内存执行读操作。
1 int main() 2 { 3 SemOp sem; 4 ShmOp shm; 5 6 sem.InitSem(); 7 shm.InitShm(); 8 9 sem.GetSem(); 10 shm.ReadShm(); 11 sem.ReleaseSem(); 12 13 shm.DelShm(); 14 sem.DelSem(); 15 return 0; 16 }
执行写操作后,可以使用ipcs命令查看系统共享内存情况。
执行代码结果: