目录
消息队列
原理
接口
指令
信号量
概念
对于信号量理论的理解
信号量的操作
信号量的指令
消息队列
原理
消息队列提供了一个从一个进程向另外一个进程发送一个数据块的方法,每个数据块都有一个类型。对消息队列的的管理也是先描述,再组织!
接口
我们发现,消息队列和共享内存的接口极其相似,消息队列的属性也保存在ipc_perm结构体中,这个结构以中的第一个元素也是__key。
与共享内存不同的是,共享内存需要挂载到地址空间,消息队列是要收发节点,
msgsnd是用来向消息队列中发数据,msgid是消息队列的id,msgp是待发数据块的起始地址,msgsz是要发的数据块一共有多少字节,msgflg默认设置为0。
msgrcv是用来收数据,msgid是从哪个消息队列接受数据,msgp要收的数据块,msgsz是要收的数据块的大小,msgtyp是所收数据的类型,msgflg默认设置为0。
我们具体来看msgp,
msgp是一个指针,指向struct msgbuf结构体,将来如果我们想发消息,可以这样:
为什么它们消息队列和共享内存的接口都是很相似的呢?原因就是它们都是System V标准。消息队列的生命周期也是随内核的。
指令
我们怎么查看消息队列呢?可以使用 ipcs -q 查看,使用ipcs -q msqid来删除消息队列。
信号量
概念
对于信号量,我们首先要理解5个概念,
- 多个执行流(进程),能看到的一份资源,是共享资源。
- 被保护起来的资源,叫临界资源,保护资源的方式主要是同步和互斥。同步就是,只有一个进程写了,另一个进程才能读,我不写,你就不能读。
- 互斥:任何一个时刻只能有一个进程在访问共享资源。
- 只要是资源,就要被程序员访问,资源被访问,就是通过代码访问。在这些代码中,包括访问共享资源的代码和不访问公共资源的代码。访问共享资源的代码叫做临界区,不访问公共资源的代码叫做非临界区。
- 所谓对共享资源进行保护,本质是对访问共享资源的代码进行保护,这就是临界区。对临界区的保护其实就是在访问临界区之前做一些工作,如加锁、解锁。
对于信号量理论的理解
信号量,也叫信号灯,目的是来保护共享资源,进而变成临界资源(即一段代码)。信号量的本质就是一个计数器,比如count==25,
现在来讲一个小故事:我们都电影院看过电影,电影院有很多座位,我只要把这个座位的票买了,我就能拥有这个座位,看电影买票的本质,是对资源的 预定 机制!我们最担心,超出资源个数的卖票。我们可以用一个计数器保证票数的安全性。电影院就相当于临界资源,买票相当于申请信号量,票数相当于信号量的初始值。申请信号量本质就是对公共资源的一种预定机制。所以,我们的步骤应该是 申请信号量--访问共享内存--释放信号量,信号量就是一把计数器,是对临界资源进行预先申请的计数器,只要申请信号量成功了,临界资源中一定有一部分是属于你的。
另外,可能还会存在超级VIP电影院,票数只有一张,同样也要申请信号量,在你看电影期间,任何人申请不到信号量,这不就是互斥吗!!!相当于把共享资源整体使用。对共享资源整体使用,其实不就是资源只有一个吗?这种信号量只有1和0计数器值,叫做二元信号量。所以,信号量分为二元信号量和多元信号量,二元信号量就是把整个资源当成整体,如果把整体资源当成很多份,那就是多元信号量。
我们可不可以用一个全局变量来充当信号量呢?不能!!!主要有两个原因:
- 全局变量不能被所有进程看到。
- gcount++/--,不是原子的。
因此,信号量也必须和共享内存、消息队列一样,也必须先让不同的进程看到同一个“计数器”。为什么信号量被纳入进程间通信的范畴呢?因为在进程间通信时,信号量也要被不同的进程看到同一块资源。也就是说,在访问公共资源(共享资源)之前,先要申请信号量,访问之后,释放信号量。
//申请信号量--
访问公共资源(共享资源)
//释放信号量++
-----------------
//也就是
if(gcount>0)gcount--;
elsewait;
不同的进程看到同一个“计数器”,这意味这什么呢?这意味着信号量也是一个公共资源!!!信号量是保护临界资源安全的,那这就要求信号量本身就是安全的。
信号量-- -> 必须是安全的 ->称为P操作
信号量++ -> 也必须是安全的 ->称为V操作
总称叫做PV操作。PV操作必须是安全的,原子性。
所以,如果现在我们有一块儿共享内存和一段访问它的代码,在访问之前要进行P操作,访问之后要进行V操作。
信号量的操作
我们只需简单了解一下信号量的操作:
信号量的指令
ipcs -s ------ 查看信号量
ipcrm -s semid ------ 删除信号量
现在,我们已经学习了共享内存、消息队列、信号量,那么OS是如何把这三者管理起来的呢?首先,它们都使用System V标准。再者,它们的接口都是通过xxxget、xxxctl来获取和删除资源。我们还发现它们都有xxxid_ds的数据结构,这个数据结构里第一个成员都是struct ipc_perm,这里简单了解一下即可~。