mq 是 Message Queue(消息队列)的缩写,在 Linux 中,消息队列是一种进程间通信机制,它允许一个或多个发送者将消息发送给一个或多个接收者,与管道和信号量等其他 IPC 机制相比,消息队列具有一些显著优点:

- 生命周期随内核:消息队列独立于创建它的进程,即使进程退出,队列中的消息仍然存在,直到被显式删除或系统重启。
- 类型化消息:可以发送和接收带有特定类型的消息,接收者可以根据类型有选择地接收消息。
- 容量更大:相比于管道(通常几 KB),消息队列可以存储更多的消息。
- 更丰富的功能:支持消息优先级、非阻塞操作等。
在 Linux 中,与消息队列交互主要有两种方式:
- 使用命令行工具:主要用于查看、管理和删除已有的消息队列。
- 使用 C 语言库函数:在应用程序中创建、发送和接收消息。
下面我们重点介绍命令行工具。
查看 ipcs 命令
ipcs 是一个强大的命令,用于查看系统上现有的 IPC 资源,包括消息队列、共享内存 和 信号量。
基本用法
要查看所有消息队列,使用 ipcs -q:

# 查看所有消息队列的摘要信息 ipcs -q # 或者使用长选项 ipcs --queues
输出解读
执行 ipcs -q 后,你会看到类似下面的输出:
------ Message Queues --------
key msqid owner perms used-bytes messages
0x00000000 65536 root 644 0 0
0x12345678 196609 myuser 660 128 2
每一列的含义如下:
- key: 消息队列的键值,这是在创建队列时指定的,用于唯一标识一个队列,如果键为
0x00000000,通常表示这是一个私有队列(通过msgget使用IPC_PRIVATE标志创建)。 - msqid: 消息队列的 ID,这是系统内部使用的唯一标识符,当你想要在程序中操作这个队列时,需要使用这个 ID。
- owner: 拥有该队列的用户。
- perms: 队列的权限,格式为八进制(
644,表示所有者有读写权限,组用户和其他用户有读权限)。 - used-bytes: 队列中当前所有消息占用的总字节数。
- messages: 队列中当前消息的总数量。
常用选项
-
-i msqid: 显示指定 ID 的消息队列的详细信息。# 查看 ID 为 196609 的消息队列详情 ipcs -i 196609
输出会包含该队列的限制(如最大字节数、最大消息数)和当前状态。
-
-p: 显示创建和最后操作该队列的进程 ID (PID)。ipcs -q -p
-
-c: 显示创建该队列的命令。ipcs -q -c
-
--human: 以人类可读的格式显示大小(KB, MB)。ipcs -q --human
删除 ipcrm 命令
ipcrm 用于删除一个或多个指定的 IPC 资源,包括消息队列、共享内存和信号量。
警告:使用 ipcrm 会立即删除指定的 IPC 资源,并且队列中所有未读的消息都会被永久销毁,请谨慎使用,特别是在生产环境中。
删除消息队列
有两种方式可以删除消息队列:
通过队列 ID (msqid) 删除
这是最常用的方式,你可以先使用 ipcs -q 找到要删除的队列的 msqid,然后用它来删除。
# 删除 ID 为 196609 的消息队列 ipcrm -q 196609
通过队列键 (key) 删除
如果你知道创建队列时使用的键,也可以直接通过键来删除。
# 删除键为 0x12345678 的消息队列 ipcrm -Q 0x12345678
删除其他 IPC 资源
ipcrm 也可以删除共享内存 (-m) 和信号量 (-s)。
# 删除 ID 为 shmid 的共享内存段 ipcrm -m shmid # 删除 ID 为 semid 的信号量集 ipcrm -s semid
强制删除所有消息队列(不推荐)
如果你想清理掉系统上所有由当前用户创建的消息队列,可以结合 ipcs 和 xargs 来实现。
# 警告:此命令会删除当前用户所有的消息队列!
ipcs -q | awk 'NR > 2 {print $2}' | xargs -n 1 ipcrm -q
命令解释:
ipcs -q: 列出所有消息队列。awk 'NR > 2 {print $2}':awk用于处理文本。NR > 2表示跳过前两行(标题行),{print $2}表示打印每一行的第二列,也就是msqid。xargs -n 1 ipcrm -q:xargs将awk输出的msqid列表作为参数,逐个(-n 1)传递给ipcrm -q命令执行。
sendmsg 和 recvmsg 命令
sendmsg 和 recvmsg 是 C 语言库函数,而不是直接的 shell 命令,Linux 提供了两个简单的命令行工具 sendmsg 和 recvmsg(通常包含在 util-linux 包中),它们是这些 C 函数的薄封装,用于在命令行上快速测试和交互消息队列。
使用 sendmsg 发送消息
# 基本语法 sendmsg [options] msqid "message_text" # 常用选项 # -t <type>: 指定消息的类型(一个正整数) # -c: 以文本模式发送 # -b: 以二进制模式发送
示例:
假设我们有一个 msqid 为 196609 的消息队列,我们想发送一条类型为 1 的消息。
# 发送一条类型为 1 的文本消息 "Hello from the command line" sendmsg -t 1 196609 "Hello from the command line"
使用 recvmsg 接收消息
# 基本语法 recvmsg [options] msqid # 常用选项 # -t <type>: 指定要接收的消息类型 # -t 0: 接收队列中第一个消息(FIFO) # -t > 0: 接收指定类型的消息 # -t < 0: 接收类型小于或等于 abs(type) 的最低类型消息 # -n: 以非阻塞模式接收,如果队列为空,立即返回而不是等待。 # -o: 从队列中移除接收到的消息(默认行为)。 # -l: 只列出消息而不从队列中移除。
示例:
从 msqid 为 196609 的队列中接收消息。
# 阻塞式接收类型为 1 的消息(如果没有,会一直等待) recvmsg -t 1 196609 # 非阻塞式接收类型为 1 的消息(如果没有,会立即报错并退出) recvmsg -t 1 -n 196609 # 只查看队列中最早的一条消息,但不删除它 recvmsg -l 196609
总结与工作流
- 创建:消息队列通常由 C 程序通过
msgget()函数创建,键值可以通过ftok()生成或手动指定。 - 查看:使用
ipcs -q查看系统上所有消息队列的状态,找到你关心的队列的msqid和key。 - 交互:使用
sendmsg和recvmsg命令向队列发送或从中读取消息,用于调试或简单的测试。 - 删除:当不再需要消息队列时,使用
ipcrm -q <msqid>或ipcrm -Q <key>将其从系统中移除,释放资源。
掌握这几个命令,你就可以在 Linux 系统上有效地管理和调试基于消息队列的应用程序了。
