进程通信(二)—— 信号量&内存共享

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

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

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

执行代码结果:

时间: 04-30

进程通信(二)—— 信号量&内存共享的相关文章

进程通信(信号量)

信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的 通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识.信号 量在此过程中负责数据操作的互斥.同步等功能. 当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用.大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直至资源可用. 当进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减 操作均为原子操作,这是由于信号量主要的作用是维护资源的互斥

进程通信之信号量笔记

                   信号量通信模块 信号量作用:主要的作用就是保护临街资源,也就是说,如果来年各 个进程都需要用到某个资源,那么通过信号量,让进程A和进程B分别占有一定的信号量,每次信号量只能准许一个进程访问,信号量是有时间限制的,这样就可以使两个进程都有机会访问同一个资源. 分类:二值信号量 :信号灯的只能取0和1,类似互斥概念.当资源为可用的时候,信号灯可以自己对资源信号灯进行修改,变为可用.二互斥锁概 念强调的是进程,进程占用完资源后,必须由该进程来解锁, 计数信号灯:信

进程通信之内存共享篇

进程通信之_ 内存共享 概念:共享内存是被多个进程共享的一部分物理内存.共享内存是进程间的共享数最快的方法,一个进程向共享内存区域写入数据,共享这个内存区域的所有进程就可以写入数据,所有进程就可以立刻看到其中的内容. 实现步骤;1.创建共享内存,使用shmget函数2.映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数 创建:int shmget (key_t key,int size,int shmflg)key 标识内存功效的键值0/ipc_private.成功返回

进程通信之共享内存

共享内存 共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自

Windows进程通信 -- 共享内存

享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 Windows 中是用 FileMapping 实现的,从具体的实现方法上看主要通过以下几步来实现: 1.调用 CreateFileMapping 创建一个内存文件映射对象: HANDLE CreateFileMapping( HANDLE hFile, // handle to file to map

进程间通信IPC:消息队列,信号量,共享内存

2015.3.4星期三 阴天 进程间通信:IPC 文件对象:记录文件描述符,文件开关等 IPC标示符:系统全局的流水号两个进程要通信,打开的是唯一的对象进行通讯,通过key操作 XSI IPC:消息队列,信号量,共享内存. ipcs 查看ip对象共享内存,信号量,消息队列等信息ipcrm 删除一个IP对象 Linux为用户提供了完善的,强大的网络功能完善的内置网络:其他操作系统不包含如此紧密的和内核结合在一起的网络部分 共享内存标示符的获取有两种方法:ftok(pathname,id)另一个是K

Linux 进程通信之 ——信号和信号量总结

如今最经常使用的进程间通信的方式有:信号,信号量,消息队列,共享内存.       所谓进程通信,就是不同进程之间进行一些"接触",这种接触有简单,也有复杂.机制不同,复杂度也不一样.通信是一个广义上的意义,不仅仅指传递一些massege.他们的用法是基本相同的,所以仅仅要掌握了一种的用法,然后记住其他的用法就能够了. 1. 信号       在我学习的内容中,主要接触了信号来实现同步的机制,据说信号也能够用来做其他的事      情,可是我还不知道做什么.       信号和信号量是

管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用

找了很久也没有找到NSPipe在IOS方面的常规使用().我试了半天终于找到它的正常的使用方法,我想对很多想使用管道会有很大的帮助.阿门,看来我是第一个吃螃蟹的人. 进程和线程间四大通信机制:管道,信号量,共享内存,socket. 四大通信机制的实际使用场景 管道是单向的.先进先出的,它把一个进程的输出和另一个进程的输入连接在一起.一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据.NSPipe包含两个文件描述符,读文件描述符合写文件描述.管道通常用在两个线程间通信

进程通信之无名信号量

和有名信号量类似,无名信号也是进程之间/线程之间通信的主要手段,唯一不同的是他不能用在不同进程之间.当然如果把无名信号量放在多个进程都可以访问的共享内存里,也可以实现进程之间的通信,但这主要还是借助于共享内存的机制.下面将根据使用无名信号量依赖的头文件.需要链接的库文件.常用的函数分别进行介绍. 依赖头文件:#include <semaphore.h> 链接依赖库: 需要链接到libpthread.so,因此makefile里需要指定-lpthread 重要函数列表: int sem_init