什么是消息队列
消息队列可以分为队列和消息
- 队列 队列是从开始到结束,有序的排放消息。消息队列是用来在应用程序发送消息,队列中存放了一些待处理的消息。
- 消息 消息用来在接受者和发送者之间传输,它本质上是一个字节数组,上面有一些头信息。一个消息示例可以是任何告诉一个系统开始处理任务或完成任务的信息。
消息队列的基本结构是简单的,有一个客户端应用程序称为生产者,创建消息,并将它们传送到消息队列。其他应用程序,称为消费者,连接到队列,并得到要处理的消息。放置在队列上的消息被存储,直到用户处理它们为止。
消息队列API
- 创建新消息队列或取得已存在消息队列
#include <sys/msg.h>
------------------------------------
int msgget(key_t key, int msgflg);
参数 | 解释 |
---|---|
key | 键值,每个消息对了key值不同,可以使用ftok生成对于的key |
msgflg | IPC_CREAT: 如果没有该队列,则创建该队列。如果该队列已经存在,返回该队列ID.IPC_CREAT & IPC_EXCL: 如果该队列不存在创建,如果存在返回失败EEXIST. |
- 向队列读或者写数据
#include <sys/msg.h>
-----------------------------------------
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
参数 | 解释 |
---|---|
msqid | 消息队列的描述符ID |
msgp | 执行消息缓冲区的指针,用来存储消息。格式如下: |
msgsz | 消息的大小 |
msgflg | IPC_NOWAIT: 如果消息队列中没有数据,则立刻返回不用等待。MSG_NOERROR:如果消息队列长度大于msgsz,截断消息。 |
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
- 设置消息队列属性
#include <sys/msg.h>
---------------------
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数 | 解释 |
---|---|
msgid | 消息队列id |
cmd | 队列执行的命令 |
bug | 执行msqid_ds的指针 |
进一步对cmd名字做详细解释
cmd | 解释 |
---|---|
IPC_STAT | 取得此队列的msqid_ds结构,存在在buf指向的结构中。 |
IPC_SET | 该命令用来设置消息队列的属性,要设置的属性存储在buf中。 |
IPC_RMID | 从内核中删除 msqid 标识的消息队列。 |
kernel关于IPC参数
名称 | 含义 |
---|---|
auto_msgmni | 根据系统memory增加,移除或者namespace创建,移除自动获取msgmni的值 |
msgmni | 该文件指定消息队列标识的最大数目,即系统范围内最大多少个消息队列。 |
msgmnb | 该文件指定一个消息队列的最大长度(bytes)。 |
msgmax | 该文件指定了从一个进程发送到另一个进程的消息的最大长度(bytes)。 |
以上信息可以根据ipcs -l获得系统的信息
代码语言:javascript复制------ Messages: Limits --------
max queues system wide = 2779
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
根据kernel.txt可以得知,auto_msgmni的值默认是1,当设置为0的时候,就不能自动获取msgmni
代码语言:javascript复制root@test:# cat /proc/sys/kernel/auto_msgmni
1
root@test:#
而在K4.4版本中。你会发现auto_msgmni居然是0,而且设置1设置失败。
代码语言:javascript复制root@test:/ # cat /proc/sys/kernel/auto_msgmni
0
root@test:/ # echo 1 > /proc/sys/kernel/auto_msgmni
root@test:/ # cat /proc/sys/kernel/auto_msgmni
0
root@test:/ #
这到底是什么原因? 可以通过查看kernel的代码得知。
代码语言:javascript复制kernel/ipc_sysctl.c
------------------------
{
.procname = "auto_msgmni",
.data = NULL,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_ipc_auto_msgmni,
.extra1 = &zero,
.extra2 = &one,
},
以上是auto_msgmni的默认配置信息,而proc_ipc_auto_msgmni是设置auto_msgmni的回调函数。
代码语言:javascript复制 static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table ipc_table;
int dummy = 0;
memcpy(&ipc_table, table, sizeof(ipc_table));
ipc_table.data = &dummy;
if (write)
pr_info_once("writing to auto_msgmni has no effect");
return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
}
可以看到一句打印: 设置auto_msgmni已经没有作用了。