当前位置:   article > 正文

linux 消息队列 msgget/msgsnd/msgrecv

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 */

           };

代码演示

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <sys/types.h>
  6. #include <sys/ipc.h>
  7. #include <sys/msg.h>
  8. #define MAX_TEXT 512
  9. struct msgbuf {
  10. long mtype;
  11. char mtext[MAX_TEXT];
  12. };
  13. int main() {
  14. struct msgbuf buf;
  15. int msqid;
  16. key_t key;
  17. if ((key = ftok(".", 123)) == -1) {
  18. perror("ftok");
  19. exit(1);
  20. }
  21. if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1) {
  22. perror("msgget");
  23. exit(1);
  24. }
  25. printf("Enter lines of text, ^D to quit:\n");
  26. buf.mtype = 1;
  27. while(fgets(buf.mtext, MAX_TEXT, stdin) != NULL) {
  28. int len = strlen(buf.mtext);
  29. if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
  30. if (msgsnd(msqid, &buf, len+1, 0) == -1) // add str end '\0'
  31. perror("msgsnd");
  32. }
  33. if (msgctl(msqid, IPC_RMID, NULL) == -1) {
  34. perror("msgctl");
  35. exit(1);
  36. }
  37. return 0;
  38. }


结尾

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/786187
推荐阅读
相关标签
  

闽ICP备14008679号