内存共享是进程间常用的通信方式,可以实现两个完全独立的进程通信。

在访问共享内存时,同时需要信号量进行访问控制。

使用ipcs -m命令可以查看系统共享内存,ipce -m + key 可以删除指定的共享内存。

image

对共享内存操作时,使用信号量对共享内存进行保护,类似与线程中的互斥锁。都可以看做是通过PV操作实现临界资源保护。

image

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命令查看系统共享内存情况。

 

执行代码结果: