zoukankan      html  css  js  c++  java
  • 进程同步(二)—— 信号量&内存共享

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

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

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

    执行代码结果:

  • 相关阅读:
    LeetCode 1109 航班预定统计
    leetcode 138 复制带随机指针的链表
    maven导入org.apache.pdfbox
    Intellij Idea 通过svn或者git提交代码时速度慢的解决办法
    java LocalDateTime 加减当前时间
    git命令--拉取代码和切换分支
    Intellij IDEA插件Free Mybatis plugin
    MySQL 生成随机字符串 uuid
    最新版Navicat Premium v15.0.26 中文破解
    算法——二分法查找
  • 原文地址:https://www.cnblogs.com/binchen-china/p/5451407.html
Copyright © 2011-2022 走看看