linux 消息队列 msgget/msgsnd/msgrecv

  


目录

前言

概述

原理

消息队列的大小

查看资源

接口

代码演示

结尾


前言

本专栏主要分享linux下并发编程相关知识,包括多进程,多线程,进程/线程间通信,并发同步控制,以及高并发下性能提升,请大家多多留言。


概述

进程间传递数据,在本专栏已经分享过共享内存,匿名/命名管道,文件映射等,今天给大家再分享一种可以通过消息包方式传递,类似于socket的方式,使用更加便捷。

原理

Linux 消息队列是一种进程间通信的机制,通过消息队列,不同进程可以彼此传递消息,实现进程间的数据共享。Linux 消息队列是一个存放消息的链表,每个消息都有一个消息类型和一个消息长度,发送方通过消息类型将消息发送到相应的消息队列中,接收方则通过消息类型从消息队列中读取相应的消息。消息队列的实现是通过内核提供的系统调用来完成的。

消息队列的大小

/proc/sys/kernel/msgmni

消息队列消息数量 MSGMNI

Linux  3.19以后默认值为32000,以前为可用内存

/proc/sys/kernel/msgmnb

消息队列最大字节数 MSGMNB

默认为16384

/proc/sys/kernel/msgmax

每个消息的最大字节数 MSGMAX

默认为8192

/proc/sys/kernel/msg_next_id

为下一个分配的IPC对象指定所需的ID

没有分配时为-1

查看资源

因为是内核资源,可以通过ipcs命令来查看已分配的消息队列,也可以查看资源限制。

[senllang@localhost msgqueue]$ ipcs -l

------ Messages Limits --------

max queues system wide = 32000

max size of message (bytes) = 8192

default max size of queue (bytes) = 16384

还有 ipcs -q查看已经有的消息队列

接口

Linux 消息队列是进程间通信中的一种方式,其中发送和接收消息的进程可以独立于消息的数据格式。在 Linux 中,消息队列由消息队列标识符、消息队列权限和消息队列中的消息组成。可以使用 msgctl()、msgget()、msgsnd() 和 msgrcv() 等函数来进行操作。其中,msgctl() 可以用于操作消息队列的权限和属性,msgget() 用于创建和访问消息队列,msgsnd() 用于将消息发送到指定消息队列,msgrcv() 则用于从消息队列中接收消息。

     消息队列涉及的头文件:

       #include <sys/types.h>

       #include <sys/ipc.h>

       #include <sys/msg.h>

       /* 获取一个System V 消息队列id */

       int msgget(key_t key, int msgflg);

    参数取值:

Key, 可以是ftok获取的,也可以是IPC_PRIVATE

msgflag, 可以取值IPC_CREAT,IPC_EXCL,还可以叠加权限进行,权限的取值与open的参数mode取值一样,只是没有可执行权限。默认指定IPC_CREAT时,没有key关联的消息队列时,就会创建,当指定IPC_EXCL时,如果不存在就会返回错误EEXIST。

        /* 发送消息 */

        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);

       调用中的flag取值 :

IPC_NOWAIT, 没有消息时立即返回;此时errno为ENOMSG。

MSG_EXCEPT,获取不是msgtyp的消息,如果队头不符合就会返回。

MSG_NOERROR,当消息超过msgsz时,会自动截断而不会报错。

/* 用于查看、设置参数,删除内核对象(用法和 shmctl 一样)*/

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

     /*消息的格式,自定义消息mtype,必须大于0;后面mtext是消息数据。这里要注意,在发送时,msgsz是不包括mtype的,只是mtext的长度 */     

struct msgbuf {

               long mtype;       /* message type, must be > 0 */

               char mtext[1];    /* message data */

           };

代码演示

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAX_TEXT 512

struct msgbuf {
long mtype;
char mtext[MAX_TEXT];
};

int main() {
struct msgbuf buf;
int msqid;
key_t key;

if ((key = ftok(".", 123)) == -1) {
    perror("ftok");
    exit(1);
}

if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1) {
    perror("msgget");
    exit(1);
}

printf("Enter lines of text, ^D to quit:\n");
buf.mtype = 1;
while(fgets(buf.mtext, MAX_TEXT, stdin) != NULL) {
    int len = strlen(buf.mtext);

    if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';

    if (msgsnd(msqid, &buf, len+1, 0) == -1) // add str end '\0'
        perror("msgsnd");
}

if (msgctl(msqid, IPC_RMID, NULL) == -1) {
    perror("msgctl");
    exit(1);
}

return 0;
}


结尾

作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。另外有什么想要了解的内容,也可以给我发邮件,互相谈讨,定知无不言。

注:未经同意,不得转载!

猜你喜欢

转载自blog.csdn.net/senllang/article/details/130186834