当前课程知识点:操作系统(RISC-V) > 第十六讲 进程通信 > 16.4 消息队列和共享内存 > 16.4 消息队列和共享内存
下面我们来讨论
消息队列和共享内存
这两种进程通讯机制
首先是消息队列
消息队列是由操作系统维护的
以字节序列为基本单位的
间接通讯机制
也就是说它是一种间接通讯机制
肯定是由操作系统维护的
它通讯的基本单位是字节序列
这是消息队列的特征
在这个图示当中
我们会看到若干个进程
可以往内核的消息队列里发送消息
然后另外的进程
可以从这消息队列里读出消息
消息是一个最基本的字节序列
多个消息按先进先出顺序
构成一个消息队列 标识相同
实际上是我这个消息队列
可以构成若干个子队列的特征
与消息队列相关的
系统调用有这样几个
也就是说我消息队列需要有一个创建
这就是依据你的标识
来创建或者获取相应的消息队列
然后有了消息队列之后
我有两个操作 发送消息和接收消息
对于消息队列来说 它后边有
缓冲区的起始位置 缓冲区的大小
以及我在写的时候它的标识
而另外一个接收跟它是类似的
前边的内容都一样
这多了一个type
详细的这些参数的含义
大家可以下去查相关的手册
还有一个是消息队列的控制
这指什么意思呢
我们进程创建和结束的时候
它所占用的资源都会被释放掉
进程从创建获取各种资源
到结束的时候
这些资源都会被释放掉
但是消息队列
是独立于创建它的进程的
所以一个进程可以创建一个消息队列
然后这个进程结束了
但这个系队列
还可以继续存在下去
从而你在后续的创建的进程
可以去读取消息队列的内容
实现两个生命周期不同的
进程之间的通讯
所以在这需要有专门的系统调用
来完成对消息队列的创建和删除
接下来的第二种机制呢 是共享内存
共享内存它是把同一段物理内存区域
映射到多个进程的地址空间里的
一种通讯机制
某种角度上来说
它应该是一种内存的共享机制
但我们这里头是
把它作为通讯来使用的
这种机制在进程和线程里的情况
是不一样的
在线程里头由于同一个进程
共享相同的地址空间
如果说你的通讯双方
是一个进程里的两个线程
那么这时候呢
这种共享内存是天然的
你不需要额外的机制就已经可以了
而如果是进程
因为每一个进程有自己的地址空间
所以在不同的进程之间
要想做共享内存的话
你必须显示的去设置一个共享内存段
然后你才能实现内存的共享
这种做法它的特点是快速方便
因为我一个进程写进去
另一个进程马上就能看得见
也没有系统调用在这里
进行用户和内核之间的切换
它的不足是仅靠共享内存
你没有办法实现完整的通讯
你需要加同步机制
以避免一个进程在写的过程当中
还没有写完之前
另一个进程从里头读
这是共享内存和它相对应的
共享内存的实现机制
我们可以用这个图来描述
两个进程的地址空间各自不同
中间是物理内存
我们把一块物理内存区域
映射到两个进程
怎么映射呢 就靠两边的页表项
不同的页表项
它是在进程地址空间里可以有相同
或者不同的逻辑地址
但是它们映射过来的时候
这一页对应的
物理内存的地址是相同的
那这时候呢
它们就映射到同一页里头了
这时候在一个进程里写
在另一个进程里我就可以读
就可以看到相应内容
从而实现这个通讯
所以这种通讯呢 它的速度是最快的
一头写进去 另一头马上就能看得到
这种通讯呢
它也没有系统调用的干预
不需要数据复制 这也是它快的原因
它的麻烦是不提供同步
你需要用其他的机制
来实现进程之间的
对共享内存访问的协调
与共享内存设置相关的
系统调用有这样几个
创建共享段
把共享段映射到
指定的进程地址空间当中
取消共享段到进程地址空间的映射
和共享段的控制
这几个系统调用
主要是完成共享关系的建立
而正常的共享数据的访问
只需要我们的读写指令就行了
不需要专门的系统调用
有了这几个映射关系之后
我们就可以通过正常的读写指令
完成两个进程之间的通讯了
但是为了保证数据的完整性
我们还需要采用信号量等
其他的同步机制来协调
不同进程对共享内存的访问冲突
避免一个进程往里写的数据还没写完
另一个进程从里读数据
从而读到的数据是错误的
有了这个协调机制之后
我们就可以完成两个进程之间的
最快速的信息交流了
到这个地方为止呢
我们就讲了四种进程之间的通讯机制
信号、管道、消息队列和共享内存
它们都有不同的适用场景
也有不同的特征
你比如说有的信息量存的比较少
但是速度比较快
有的信息量比较大
但是前后的协调机制比较复杂
希望大家下去之后通过实际的例子
来尝试几种不同通讯机制
看它们各有什么样的特征
更有兴趣的同学可以在我们的ucore里
对这些通讯机制进行实现和完善
今天的课就上到这里
下课
-1.1 课程概述
--课程概述
-1.2 教学安排
--视频
-1.3 什么是操作系统
--Video
-1.4 为什么学习操作系统,如何学习操作系统
--Video
-1.5 操作系统实例
--视频
-1.6 操作系统的演变
--视频
-1.7 操作系统结构
--视频
-1.8 OS实验概述
--视频
-2.1 从OS角度看计算机系统
-2.2 从OS角度看RISC-V
-2.3 Rust语言与系统编程
-2.4 RISC-V CPU启动
-2.5 RISC-V CPU启动进一步分析
-3.1 基本概念与原理
-3.2 硬件架构支持
-3.3 中断处理机制
-3.4 系统调用
--3.4 系统调用
-4.1 计算机体系结构和内存层次
-4.2 地址空间和地址生成
-4.3 连续内存分配
-4.4 碎片整理
--4.4 碎片整理
-4.5 伙伴系统
--4.5 伙伴系统
-4.6 SLAB分配器
-5.1 非连续内存分配的需求背景
-5.2 段式存储管理
-- 5.2 段式存储管理
-5.3 页式存储管理
-5.4 页表概述
--5.4 页表概述
-5.5 快表和多级页表
-5.6 RISC-V页映射机制
-5.7 使能RISC-V页表
-6.1 虚拟存储的需求背景
-6.2 覆盖和交换
-6.3 局部性原理
-6.4 虚拟存储概念
-6.5 虚拟页式存储
-6.6 缺页异常
--6.6 缺页异常
-6.7 RISC-V缺页异常
-7.1 页面置换算法的概念
-7.2 最优算法、先进先出算法和最近最久未使用算法
-7.3 时钟置换算法和最不常用算法
-7.4 Belady现象和局部置换算法比较
-7.5 页表自映射
-8.1 工作集置换算法
-8.2 缺页率置换算法
-8.3 抖动和负载控制
-8.4 面向缓存的页替换算法
-9.1 进程的概念
-9.2 进程控制块
-9.3 进程状态
--9.3 进程状态
-9.4 三状态进程模型
-9.5 挂起进程模型
-9.6 线程的概念
-9.7 用户线程
--9.7 用户线程
-9.8 内核线程
--9.8 内核线程
-9.9 进程地址空间与熔断 (meltdown) 漏洞
-10.1 进程切换
-10.2 进程创建
-10.3 进程加载
-10.4 进程等待与退出
-10.5 rCore进程和线程控制
-11.1 处理机调度概念
-11.2 调度准则
-11.3 先来先服务、短进程优先和最高响应比优先调度算法
--11.3 先来先服务、短进程优先和最高响应比优先调度算法
-11.4 时间片轮转、多级反馈队列、公平共享调度算法和ucore调度框架
--11.4 时间片轮转、多级反馈队列、公平共享调度算法和ucore调度框架
-11.5 实时调度
-11.6 优先级反置
-11.7 rCore调度框架
-12.1 对称多处理与多核架构
-12.2 多处理器调度概述
-12.3 O(1)调度
-12.4 CFS调度
-12.5 BFS调度算法
-13.1 背景
--13.1 背景
-13.2 现实生活中的同步问题
-13.3 临界区和禁用硬件中断同步方法
-13.4 基于软件的同步方法
-13.5 高级抽象的同步方法
-14.1 信号量
--14.1 信号量
-14.2 信号量使用
-14.3 管程
--14.3 管程
-14.4 哲学家就餐问题
-14.5 读者-写者问题
-14.6 Rust语言中的同步机制
-15.1 死锁概念
-15.2 死锁处理方法
-15.3 银行家算法
-15.4 死锁检测
-15.5 并发错误检测
-16.1 进程通信概念
-16.2 信号和管道
-16.3 Linux信号机制
-16.4 消息队列和共享内存
-16.5 D-Bus机制
-16.6 Binder机制
-17.1 文件系统和文件
-17.2 文件描述符
-17.3 目录、文件别名和文件系统种类
-17.4 虚拟文件系统
-17.5 文件缓存和打开文件
-17.6 文件分配
-17.7 空闲空间管理和冗余磁盘阵列RAID
-18.1 FAT文件系统
-18.2.1 EXT4文件系统-历史
-18.2.2 EXT4文件系统-支持大容量存储
-18.2.3 EXT4文件系统-支持恢复异常
-18.3 ZFS文件系统
-19.1 I/O特点
-19.2 I/O结构
-19.3 I/O数据传输
-19.4 磁盘调度
-19.5 Linux I/O子系统
-20.1 Linux内核错误分析
-20.2.1 用rust写操作系统-系统编程语言rust
--20.2.1 用rust写操作系统-系统编程语言rust
-20.2.2 用rust写操作系统-rust与操作系统开发
--20.2.2 用rust写操作系统-rust与操作系统开发
-21.1 Background
-21.2 Futures in Rust
-21.3 Generators and async/await
--21.3 Generators and async/await
-21.4 Self-Referential Structs & Pin
--21.4 Self-Referential Structs & Pin
-21.5 Waker and Reactor
-22.1 Overview
-22.2.1 How VMM works - CPU
-22.2.2 How VMM works - memory & I/O