7. 消息队列
7.1 消息队列的概念
这里讨论的消息队列是操作系统层面的概念,不同于应用组件内部的消息中间件。简单来说,就是操作系统内核维护的一个队列结构。
7.2 消息队列的原理
消息队列是操作系统提供的一种 IPC(进程间通信)机制。它允许用户设置一个 key 值,多个进程通过约定好的 key 访问同一个队列。
双方通过往消息队列中插入节点来交换数据。在内核中,消息队列也有自己的描述结构体。需要注意的是,如果数据节点只包含纯数据,操作系统无法区分这是属于进程 A 的还是进程 B 的。因此,必须保证数据块是有类型的。
消息队列是一种让进程给另一个进程发送有类型数据块的方式。
相关的系统调用包括创建、发送和接收等接口。
7.3 消息队列的接口
主要涉及以下系统调用:
msgget:创建或获取消息队列标识符。msgsnd:向队列发送消息。msgrcv:从队列接收消息。msgctl:控制消息队列(如删除)。
7.4 消息队列的一些命令
在终端中可以使用相关命令查看或删除消息队列,例如 ipcs -q 查看,ipcrm -q 删除。
8. 信号量
在使用共享内存时,我们知道它缺乏保护机制,而信号量可以用来保护共享内存。
这里我们重点理解信号量是什么。虽然在线程部分会深入探讨同步互斥,但在多进程层面,核心问题依然是:如何让不同的进程看到同一份资源?
引入新的解决方案往往会带来新问题。比如,多个进程并发访问同一资源时会出现错误(如互相覆盖)。
8.1 概念补充
8.1.1 共享资源和临界资源
- 共享资源:多个执行流(进程)能够看到的公共资源。
- 临界资源:被保护起来的资源,一次只允许一个执行流访问。
8.1.2 互斥和同步
- 互斥:任何时刻只允许一个执行流访问资源。就像 ATM 机取钱或上厕所关门,不想被别人打扰。
- 同步:让多个进程按顺序执行。一个进程在等待另一个进程完成特定操作。
互斥 + 同步 + 共享资源 = 临界资源(被保护的共享资源)
8.1.3 和程序员有什么关系?
作为开发者,我们需要关注代码如何访问这些资源。举个例子,父子进程都往同一个显示器打印内容时,经常发生输出错乱。这是因为 Linux 下一切皆文件,stdout 是共享资源且未被保护。为了防止错乱,需要通过同步与互斥机制来保护。
8.1.4 临界区
站在程序员视角,访问公共资源的代码段被称为【临界区】,不访问的则是【非临界区】。
进入临界区前加锁,离开时解锁。通过这种方式将临界资源保护起来。
8.1.5 保护访问公共资源的代码
核心逻辑是在临界区前后添加同步原语,确保同一时间只有一个进程能修改共享数据。
8.2 信号量的三个问题
学习信号量可以借鉴'是什么、为什么、怎么办'的思路。
8.2.1 (概念)信号量是什么?
很多教材将其翻译为'信号灯'。
- 定义:用来实现同步和互斥的一种技术。
- 场景:公共资源的整体访问(如 ATM),或局部使用(如电影院座位)。


