消息队列

  • 消息队列是内核中的一个链表
  • 用户进程将数据传输到内核后,内核重新添加一些如用户ID、组ID、读写进程的ID和优先级等相关信息后并打包成一个数据包称为消息
  • 允许一个或多个进程往消息队列中读写消息,但一个消息只能被一个进程读取,读取完毕后自动删除
  • 消息队列具有一定的FIFO的特性,消息可以按照顺序发送到队列中,也可以几种不同的方式从队列中读取。每一个消息队列在内核中用一个唯一的IPC标识ID表示
  • 消息队列的实现包括创建和打开队列发送消息读取消息控制消息队列四种操作。

消息队列属性

struct msqid_ds
{
struct ipc_perm msg_perm;
msgqnum_t msg_qnum; //消息数量
msglen_t msg_qbytes; //消息最大字节数
pid_t msg_lspid; //最后一次发送消息进程的pid
pid_t msg_lrpid; //最后一次接收消息的pid
pid_t msg_stime; //最后一次消息发送的时间
pid_t msg_ctime; //最后一次消息改变的时间
};

打开或创建消息队列

#include <sys/msg.h>
int msgget(key_t key,int flag);
//返回:如果成功,返回内核中消息队列的标识ID,出错返回-1
  • 参数

    • key:用户指定的消息队列键值
    • flag:IPC CREAT,IPC EXCL等权限组合
  • 若创建消息队列,key可以指定键值,也可以设置为IPC_PRIVATE(0)。若打开进行查询,则key不能为0,必须是一个非零的值,否则查询不到

消息队列控制

#include <sys/msg.h>
int msgctl(int msgid,int cmd,struct msqid_ds *buf);
//返回:成功返回0,出错返回-1
  • 参数

    • msgid:消息队列ID
    • buf:消息队列属性指针
    • cmd
      • IPC_STAT:获取消息队列的属性,取此队列的msqid_ds结构,并放在buf指向的结构中
      • IPC_SET:设置属性,按由buf只想的结构中的值,设置与此队列相关的结构中的字段
      • IPC_RMID:删除队列,从系统中删除该队列以及在队列上的所有数据。

发送消息

#include <sys/msg.h>
int msgsnd(int msgqid,const void *ptr,size_t nbytes,int flag);
//成功返回0,出错返回-1 ptr:
struct mymesg
{
long mtype;//消息类型
char mtext[512];//消息数据本身
};
  • nbytes 指定消息的大小,不包括mtype的大小
  • mtype指消息的类型,由一个整数来表示,且大于0
  • mtext消息数据本身
  • 在Linux中,消息的最大长度是4056个字节,其中包括mtype,占4个字节
  • 结构体mymesg用户可自定义,但第一个成员必须是mtype
  • 参数flag
    • 0:阻塞
    • IPC_NOWAIT:类似文件I/O的非阻塞
    • 若消息队列满(或者是队列中的消息总数等于系统限制值,或队列中的字节数等于系统限制值),则指定IPC_NOWAIT使得msgsnd立即出错返回EAGAIN。如果指定0,则
      • 阻塞直到有空间可以容纳要发送的消息
      • 或从系统中删除了此队列
      • 或捕捉到一个信号,并从信号处理程序返回

接收消息

#include <sys/msg.h>
ssize_t msgrcv(int msgqid,void *ptr,size_t nbytes,long type,int flag);
//成功返回消息数据部分的长度,出错返回-1
  • 参数

    • magqid:消息队列的ID
    • ptr:指向存放消息的缓存
    • nbytes:消息缓存的大小,不包括mtype的大小。计算方式
      • nbytes=sizeof(struct mymesg)-sizeof(long)
    • type:消息类型
      • type==0:获得消息队列中的第一个消息
      • type>0:获得消息队列中类型type的第一个消息
      • type<0:获得消息队列中小于或等于type绝对值的消息
    • flag:0或者IPC_NOWAIT

消息队列发送消息

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h> typedef struct
{
long type;//消息类型
int start;//消息数据本身(包括start和end)
int end;//
}MSG; //往消息队列中发送消息
int main(int argc,char *argv[])
{
if(argc<2)
{
printf("usage:%skey\n",argv[0]);
exit(1);
}
key_t key=atoi(argv[1]);
printf("key:%d\n",key); //创建消息队列
int msq_id;
if((msq_id=msgget(key,IPC_CREAT|IPC_EXCL|0777))<0)
{
perror("msgget error");
}
printf("msq id:%d\n",msq_id); //定义要发送的消息
MSG m1={4,4,400};
MSG m2={2,2,200};
MSG m3={1,1,100};
MSG m4={6,6,600};
MSG m5={6,60,6000}; //发送消息到消息队列
if(msgsnd(msq_id,&m1,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd error");
}
if(msgsnd(msq_id,&m2,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd error");
}
if(msgsnd(msq_id,&m3,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd error");
}
if(msgsnd(msq_id,&m4,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd error");
}
if(msgsnd(msq_id,&m5,sizeof(MSG)-sizeof(long),IPC_NOWAIT)<0)
{
perror("msgsnd error");
} //发送后区获取消息队列中消息的总数
struct msqid_ds ds;
if(msgctl(msq_id,IPC_STAT,&ds)<0)
{
perror("msgctl error");
}
printf("msg total:%ld\n",ds.msg_qnum); exit(0);
}

运行程序,指定key

$ ./msq_snd 1024
key:1024
msq id:65536
msg total:5

使用命令查看IPCS

$ ipcs -q

使用命令删除MSQ

$ ipcrm -q 65536

IPC 进程间通信方式——消息队列的更多相关文章

  1. IPC通信:Posix消息队列

    IPC通信:Posix消息队列 消息队列可以认为是一个链表.进程(线程)可以往里写消息,也可以从里面取出消息.一个进程可以往某个消息队列里写消息,然后终止,另一个进程随时可以从消息队列里取走这些消息. ...

  2. [转]Linux进程间通信——使用消息队列

    点击此处阅读原文 另收藏作者ljianhui的专栏初学Linux 下面来说说如何使用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linu ...

  3. Linux进程间通信——使用消息队列

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道   一.什么是消息队列 消息队列提 ...

  4. 进程间通信--POSIX消息队列

    相关函数: mqd_t mq_open(const char *name, int oflag); mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, si ...

  5. IPC编程之消息队列

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面3类: 1.消息传递(管道.FIFO.消息队列) 2.同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 3.共享内存(匿名的和具名的) ...

  6. IPC 进程间通信方式——管道

    进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...

  7. 练习--LINUX进程间通信之消息队列MSG

    https://www.ibm.com/developerworks/cn/linux/l-ipc/part3/ 继续坚持,或许不能深刻理解,但至少要保证有印象. ~~~~~~~~~~~~~~ 消息队 ...

  8. Linux进程间通信(消息队列/信号量+共享内存)

    写在前面 不得不说,Deadline果真是第一生产力.不过做出来的东西真的是不堪入目,于是又花了一早上重写代码. 实验内容 进程通信的邮箱方式由操作系统提供形如 send()和 receive()的系 ...

  9. Linux进程间通信(二) - 消息队列

    消息队列 消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据. 消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点(管道请查阅我的另一篇文章 ...

随机推荐

  1. yolo3 车辆检测

    1. 使用原在imagenet上训练好的weights用于特征提取 darknet53.conv.74 可从yolo官网下载 2. 车辆检测数据集及其label制作 a. voc car类包含1161 ...

  2. 阿里云Zabbix安装实践过程

    1.配置阿里云zabbix yum源 [root@VM_0_8_centos ~]# rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix/3.0/rhe ...

  3. synchronized(三) 锁的膨胀过程(锁的升级过程)深入剖析

    警告⚠️:本文耗时很长,先做好心理准备................哈哈哈 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是 ...

  4. Spring Boot(2)中的yaml配置简介

    搞Spring Boot的小伙伴都知道,Spring Boot中的配置文件有两种格式,properties或者yaml,一般情况下,两者可以随意使用,选择自己顺手的就行了,那么这两者完全一样吗?肯定不 ...

  5. mysql开启和关闭安全模式

    今天在进行数据库UPDATE的时候出了一个问题,我把非主键的字段当作UPDATE的条件(筛选条件)时,提示了如下的语句 Error Code: 1175. You are using safe upd ...

  6. 爬取百度贴吧前1000页内容(requests库面向对象思想实现)

    此程序以李毅吧为例子,以面向对象的设计思想实现爬取保存网页数据,暂时并未用到并发处理,以后有机会的话会加以改善 首先去百度贴吧分析贴吧地址栏中url后的参数,找到分页对应的参数pn,贴吧名字对应的参数 ...

  7. python-day31(正式学习)

    一.单机架构 应用领域: 植物大战僵尸 office 二.CS架构 应用领域: QQ 大型网络游戏 计算机发展初期用户去取数据,直接就去主机拿,从这里开始就分出了客户端和服务端. 客户端:用户安装的软 ...

  8. TCP/IP 协议是如何保证数据可靠性的?

    原文: 网络基础:TCP协议-如何保证传输可靠性 TCP协议传输的特点主要就是面向字节流.传输可靠.面向连接.这篇博客,我们就重点讨论一下TCP协议如何确保传输的可靠性的. 确保传输可靠性的方式TCP ...

  9. C++ 数组操作符重载、函数对象分析、赋值操作符

    string类型访问单个字符 #include <iostream> #include <string> #include <sstream> using name ...

  10. java中如果删除导入的jar包,工程出现叹号解决方案

    第一步:在工程上右键 第二步:选中build Path 第三步:选择Configue bulid path 第四步:选择liberary 第五步:鼠标点击带红色叉叉的 第六步:点击edit 第七步:点 ...