Linux消息队列

2022-05-08 16:47:40 浏览数 (1)

什么是消息队列

消息队列可以分为队列和消息

  • 队列 队列是从开始到结束,有序的排放消息。消息队列是用来在应用程序发送消息,队列中存放了一些待处理的消息。
  • 消息 消息用来在接受者和发送者之间传输,它本质上是一个字节数组,上面有一些头信息。一个消息示例可以是任何告诉一个系统开始处理任务或完成任务的信息。

消息队列的基本结构是简单的,有一个客户端应用程序称为生产者,创建消息,并将它们传送到消息队列。其他应用程序,称为消费者,连接到队列,并得到要处理的消息。放置在队列上的消息被存储,直到用户处理它们为止。

消息队列API

  • 创建新消息队列或取得已存在消息队列
代码语言:javascript复制
#include <sys/msg.h>
------------------------------------
int msgget(key_t key, int msgflg);

参数

解释

key

键值,每个消息对了key值不同,可以使用ftok生成对于的key

msgflg

IPC_CREAT: 如果没有该队列,则创建该队列。如果该队列已经存在,返回该队列ID.IPC_CREAT & IPC_EXCL: 如果该队列不存在创建,如果存在返回失败EEXIST.

  • 向队列读或者写数据
代码语言:javascript复制
#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,截断消息。

代码语言:javascript复制
 struct msgbuf 
 {
      long mtype;       /* message type, must be > 0 */
      char mtext[1];    /* message data */
 };
  • 设置消息队列属性
代码语言:javascript复制
#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已经没有作用了。

0 人点赞