下面我们来讨论
消息队列和共享内存
这两种进程通讯机制
首先是消息队列
消息队列是由操作系统维护的
以字节序列为基本单位的
间接通讯机制
也就是说它是一种间接通讯机制
肯定是由操作系统维护的
它通讯的基本单位是字节序列
这是消息队列的特征
在这个图示当中
我们会看到若干个进程
可以往内核的消息队列里发送消息
然后另外的进程
可以从这消息队列里读出消息
消息是一个最基本的字节序列
多个消息按先进先出顺序
构成一个消息队列 标识相同
实际上是我这个消息队列
可以构成若干个子队列的特征
与消息队列相关的
系统调用有这样几个
也就是说我消息队列需要有一个创建
这就是依据你的标识
来创建或者获取相应的消息队列
然后有了消息队列之后
我有两个操作 发送消息和接收消息
对于消息队列来说 它后边有
缓冲区的起始位置 缓冲区的大小
以及我在写的时候它的标识
而另外一个接收跟它是类似的
前边的内容都一样
这多了一个type
详细的这些参数的含义
大家可以下去查相关的手册
还有一个是消息队列的控制
这指什么意思呢
我们进程创建和结束的时候
它所占用的资源都会被释放掉
进程从创建获取各种资源
到结束的时候
这些资源都会被释放掉
但是消息队列
是独立于创建它的进程的
所以一个进程可以创建一个消息队列
然后这个进程结束了
但这个系队列
还可以继续存在下去
从而你在后续的创建的进程
可以去读取消息队列的内容
实现两个生命周期不同的
进程之间的通讯
所以在这需要有专门的系统调用
来完成对消息队列的创建和删除
接下来的第二种机制呢 是共享内存
共享内存它是把同一段物理内存区域
映射到多个进程的地址空间里的
一种通讯机制
某种角度上来说
它应该是一种内存的共享机制
但我们这里头是
把它作为通讯来使用的
这种机制在进程和线程里的情况
是不一样的
在线程里头由于同一个进程
共享相同的地址空间
如果说你的通讯双方
是一个进程里的两个线程
那么这时候呢
这种共享内存是天然的
你不需要额外的机制就已经可以了
而如果是进程
因为每一个进程有自己的地址空间
所以在不同的进程之间
要想做共享内存的话
你必须显示的去设置一个共享内存段
然后你才能实现内存的共享
这种做法它的特点是快速方便
因为我一个进程写进去
另一个进程马上就能看得见
也没有系统调用在这里
进行用户和内核之间的切换
它的不足是仅靠共享内存
你没有办法实现完整的通讯
你需要加同步机制
以避免一个进程在写的过程当中
还没有写完之前
另一个进程从里头读
这是共享内存和它相对应的
共享内存的实现机制
我们可以用这个图来描述
两个进程的地址空间各自不同
中间是物理内存
我们把一块物理内存区域
映射到两个进程
怎么映射呢 就靠两边的页表项
不同的页表项
它是在进程地址空间里可以有相同
或者不同的逻辑地址
但是它们映射过来的时候
这一页对应的
物理内存的地址是相同的
那这时候呢
它们就映射到同一页里头了
这时候在一个进程里写
在另一个进程里我就可以读
就可以看到相应内容
从而实现这个通讯
所以这种通讯呢 它的速度是最快的
一头写进去 另一头马上就能看得到
这种通讯呢
它也没有系统调用的干预
不需要数据复制 这也是它快的原因
它的麻烦是不提供同步
你需要用其他的机制
来实现进程之间的
对共享内存访问的协调
与共享内存设置相关的
系统调用有这样几个
创建共享段
把共享段映射到
指定的进程地址空间当中
取消共享段到进程地址空间的映射
和共享段的控制
这几个系统调用
主要是完成共享关系的建立
而正常的共享数据的访问
只需要我们的读写指令就行了
不需要专门的系统调用
有了这几个映射关系之后
我们就可以通过正常的读写指令
完成两个进程之间的通讯了
但是为了保证数据的完整性
我们还需要采用信号量等
其他的同步机制来协调
不同进程对共享内存的访问冲突
避免一个进程往里写的数据还没写完
另一个进程从里读数据
从而读到的数据是错误的
有了这个协调机制之后
我们就可以完成两个进程之间的
最快速的信息交流了
到这个地方为止呢
我们就讲了四种进程之间的通讯机制
信号、管道、消息队列和共享内存
它们都有不同的适用场景
也有不同的特征
你比如说有的信息量存的比较少
但是速度比较快
有的信息量比较大
但是前后的协调机制比较复杂
希望大家下去之后通过实际的例子
来尝试几种不同通讯机制
看它们各有什么样的特征
更有兴趣的同学可以在我们的ucore里
对这些通讯机制进行实现和完善
今天的课就上到这里
下课