利用semaphore实现shm进程通信
一.进程通信方式简介
总结起来,进程通信包括:
其中,信号量+共享存储区、消息传递,称作XSI IPC(InterProcess Communication)。
二. 信号量+共享存储区的进程间通信
2.1 共享存储问题分析
本文介绍的进程通信方法,是在内存中开辟一块共享内存区,再利用信号量实现访问的互斥、阻塞、初始化判别。共享存储的原理如图1所示:
图1 共享存储机制的物理、逻辑示意图
假设进程A、B需要相互通信,则各自设一个结构体来存储共享存储(以下简称shm)的描述信息。其中,shm_A.shmkey=shm_A.shmkey,shm_A.shmid=shm_A.shmid,但是,shm_A.shmdata_pointer与shm_B.shmdata_pointer 是不想等的,道理很简单:两者分别在不同的进程,它们各自描述自己所在进程的shm的虚拟地址,然后通过内核映射到内存中shm的物理地址(SharedAddr)。
A、B(或者更多的进程,本文只介绍两个进程)通信,自然引发出如何互斥、如何同步的问题。A、B不能同时访问SharedAddr,解决互斥问题,即可实现异步通信,即:接收方需要数据时,就访问SharedAddr;发送方需要更新数据时,就直接往SharedAddr写数据。另外一个需求就是,接收方希望即时获取新的数据,即:发送方一更新数据,接收方立刻获取到新的数据,这样就要求接收端可以休眠(或阻塞)等待新数据。以上两个问题可以利用信号量(以下简称sem)来解决:使用两个信号量,一个用于互斥、一个用于唤醒通知。
引进信号量以后,又有一个新的问题:多个进程使用同一个key的sem,而一个sem的创建其实只需要一次初始化,引用sem时如何知道这个sem是否已经经过初始化了呢?我们知道,sem是信号量集,还可以再加一个信号
量,利用此信号量标志sem已经初始化了。
综上所述,基于shm通信,可利用3个semaphore,以下简称为:SEM_MUTEXT、SEM_BLOCKING、SEM_INITIAL。在内存开辟共享内存块,将该内存块地址映射各进程中,进程通过某种机制访问映射地址,即可读、写共享内存块。
2.2 PV操作过程
有了SEM_MUTEXT、SEM_BLOCKING、SEM_INITIAL,进程进行PV操作可通过以下步骤实现(假设shm的地址是shmdata_pointer):
(1)对于P操作:
Step1:对SEM_MUTEXT做semop操作,动作为“-1”,以锁住资源,此时其他进程必须等待资源释放才能访问;Step2:将要写进的数据的长度datasize写到地址shmdata_pointer;
Step3:将有效数据写到shmdata_pointer+sizof(unsigned short);
Step4:对SEM_MUTEXT做semop操作,动作为“+1”,以释放资源,此时其他进程可以访问资源;
Step5:对SEM_BLOCKING注意semop操作,动作为“-1”;之后立刻再做semop操作,动作为“+1”。这个步骤只对V操作阻塞等待模式才有效。
(2)对于V操作:
进程间通信 共享内存Step1:判断是否阻塞模式,是则对SEM_BLOCKING做semop操作,动作为“0”,如此等待P操作中对SEM_BLOCKING 的“-1”动作,当“-1”动作发生,V进程立刻被唤醒,程序立刻执行下去;而P进程立刻“+1”动作,相当于“开门”放行一个人之后立刻“关门”。(注意:此处科学性还不够,只能由一个V进程等待,不能确保多个V进程都能读到刚更新的数据,不过该思想是能够拓展到多个V进程的模式的。)
Step2:对SEM_MUTEXT做semop操作,动作为“-1”,以锁住资源,此时其他进程必须等待资源释放才能访问;Step3:读取地址shmdata_pointer为首地址,长度为sizeof(unsigned short)的内容,赋给datasize;
Step4:读取地址shmdata_pointer+sizeof(unsigned short)为首地址,长度为datasize的内容,即有效数据;
Step5:对SEM_MUTEXT做semop操作,动作为“+1”,以释放资源,此时其他进程可以访问资源。
对于信号量初始化的过程,难点在于判断信号量是否已经被初始化过,其过程如下:
Step1:获取sem标识符:semid = semget(key, 3, IPC_CREAT)。
Step2:判断SEM_INITIAL是否已经被标志:semctl(semid, SEM_INITIAL, GETVAL)。其返回值若等于SEM_INITIAL_VAL,则说明已经初始化过,否则进行下一步。
Step3:sem初始化,向SEM_MUTEXT、SEM_BLOCKING、SEM_INITIAL分别SETVAL为:1,1,SEM_INITIAL_VAL。
三.代码实现
3.1 _shm_.h 和_shm_.c
(2)_shm_.c

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。