消息队列的定义遍地都是,不想移驾,请看下文:

一、定义:

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。

每个数据块都被认 为是有一个类型,接收者进程接收的数据块可以有不同的类型值。我们可以通过发送消息来避免命名管道的同步和阻塞问题。

消息队列与管道不同的是,消息队列是基于消息的, 而管道是基于字节流的,且消息队列的读取不一定是先入先出。

消息队列与命名管道有一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)

关于上下限:

二、IPC对象数据结构

内核为每个IPC对象维护一个数据结构(/usr/include/linux/ipc.h)

struct ipc_perm
{
key_t __key; /* Key supplied to xxxget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */ 
    unsigned short __seq;/* Sequence number */
};

消息队列,共享内存和信号量都有这样一个共同的数据结构。

三、消息队列结构:

可以看到第一个条目就是IPC结构体,即是共有的,后面的都是消息队列所私有的成员,消息队列是用链表实现的。

四、相关函数解释:

1、msgget函数
该函数用来创建和访问一个消息队列。它的原型为:
int msgget(key_t, key, int msgflg); 
与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。
1.msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。

2.msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。

3.它返回一个以key命名的消息队列的标识符(非零整数),失败时返回-1.

2、msgsnd函数
该函数用来把消息添加到消息队列中。它的原型为:
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg); 
1.msgid是由msgget函数返回的消息队列标识符。

2.msg_ptr是一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,指针msg_ptr所指向的消息结构一定要是以一个长整型成员变量开始的结构体;

    接收函数将用这个成员来确定消息的类型。所以消息结构要定义成这样:
struct my_message{
long int message_type;
/* The data you wish to transfer*/
};
3.msg_sz是msg_ptr指向的消息的长度,注意是消息的长度,而不是整个结构体的长度,也就是说msg_sz是不包括长整型消息类型成员变量的长度。

4.msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情。

   如果调用成功,消息数据的一分副本将被放到消息队列中,并返回0,失败时返回-1.

3、msgrcv函数
该函数用来从一个消息队列获取消息,它的原型为
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
1.msgid, msg_ptr, msg_st的作用也函数msgsnd函数的一样。

2.msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。

     如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。

3.msgflg用于控制当队列中没有相应类型的消息可以接收时将发生的事情。

调用成功时,该函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息。失败时返回-1.

4、msgctl函数
该函数用来控制消息队列,它与共享内存的shmctl函数相似,它的原型为:
int msgctl(int msgid, int command, struct msgid_ds *buf);  
command是将要采取的动作,它可以取3个值,

    IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。

    IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值

    IPC_RMID:删除消息队列

buf是指向msgid_ds结构的指针,它指向消息队列模式和访问权限的结构。msgid_ds结构至少包括以下成员:
struct msgid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
成功时返回0,失败时返回-1.

五、用消息队列实现进程间通信实例

让两个没有任何联系的进程间通信,以下是Linux下的代码:
1.server.c

2.client.c

3.comm.h



4.comm.c





代码主要就贴comm.c里的:

#include"comm.h"

static int com_msg_queue(int flags)
{
key_t _key = ftok(_PROJ_NAME_,_PROJ_ID_);
if(_key < 0)
{
perror("ftok");
return -1;
} int msg_id = msgget(_key,flags); //
if(msg_id < 0)
{
perror("msgget");
} return msg_id;
} int create_msg_queue()
{
int flags = IPC_CREAT | IPC_EXCL | 0644;
return com_msg_queue(flags);
} int get_msg_queue()
{
int flags = IPC_CREAT;
return com_msg_queue(flags);
} int destroy_msg_queue(int msg_id)
{
if(msgctl(msg_id,IPC_RMID,NULL) < 0)
{
perror("msgctl");
return -1;
}
return 0;
} int send_msg(int msg_id,int t,const char* msg)
{
struct msgbuf _msg;
_msg.mtype = t;
strncpy(_msg.mtext,msg,strlen(msg)+1); if(msgsnd(msg_id,&_msg,sizeof(_msg.mtext),0) < 0)
{
perror("msgsnd");
return -1;
}
return 0;
} int recv_msg(int msg_id,int t,char* out)
{
struct msgbuf _msg;
_msg.mtype = t;
memset(_msg.mtext,'\0',sizeof(_msg.mtext));
if(msgrcv(msg_id,&_msg,sizeof(_msg.mtext),t,0) < 0)
{
perror("msgrcv");
return -1;
}
else
{
strcpy(out,_msg.mtext);
}
return 0;
}

分析:主要是两个.C文件,两个main函数,两个进程,一个进程发送,一个进程接受,模拟实现连个进程间的通信,代码中最后的两个函数,一个是发送,一个是接受;

六、消息队列与命名管道的比较

消息队列跟命名管道有不少的相同之处,通过与命名管道一样,消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接收的方式来传递数据的。

在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。

与命名管道相比,消息队列的优势在于:

1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。

2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。

3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。

赐教!

Linux下进程间通信--消息队列的更多相关文章

  1. Linux下的消息队列

    文章链接:https://blog.csdn.net/qq_38646470/article/details/80169406

  2. Windows与Linux下进程间通信技术比较

    一般我们写的程序都是以单个进程的方式来运行的,比较少涉及到多进程.特别是在windows下,因为Windows是按照线程来分配CPU时间片的,线程是最小的调度单位,所以在Windows下更多的用到多线 ...

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

    一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的 ...

  4. Linux下进程间通信的六种机制详解

    linux下进程间通信的几种主要手段:        1.管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具 ...

  5. Net平台下的消息队列介绍

    Net平台下的消息队列介绍   本系列主要记录最近学习消息队列的一些心得体会,打算形成一个系列文档.开篇主要介绍一下.Net平台下一些主流的消息队列框架.       RabbitMQ:http:// ...

  6. PHP 进程间通信——消息队列(msg_queue)

    PHP 进程间通信--消息队列 本文不涉及PHP基础库安装.详细安装说明,请参考官网,或期待后续博客分享. 1.消息队列函数准备 <?php//生成一个消息队列的key$msg_key = ft ...

  7. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

  8. 【微服务专题之】.Net6下集成消息队列上-RabbitMQ

    ​ 微信公众号:趣编程ACE关注可了解更多的.NET日常实战开发技巧,如需源码 请公众号后台留言 源码;[如果觉得本公众号对您有帮助,欢迎关注] .Net中RabbitMQ的使用 [微服务专题之].N ...

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

    前面两篇文章分解介绍了匿名管道和命名管道方式的进程间通信,本文将介绍Linux消息队列(posix)的通信机制和特点. 1.消息队列 消息队列的实现分为两种,一种为System V的消息队列,一种是P ...

随机推荐

  1. 小程序for循环中通过index实现单个点击事件

    <!--xml--> <view class='content3-list' wx:for="{{listItems}}" > <view class ...

  2. C#图解教程 第八章 表达式和运算符

    表达式和运算符 表达式字面量 整数字面量实数字面量字符字面量字符串字面量 求值顺序 优先级结合性 简单算术运算符求余运算符关系比较运算符和相等比较运算符递增运算符和递减运算符条件逻辑运算符逻辑运算符移 ...

  3. C#图解教程 第十一章 枚举

    枚举 枚举 设置底层类型和显式值隐式成员编号 位标志 Flags特性使用位标志的示例 关于枚举的补充 枚举 枚举 枚举是由程序员定义的类型与类或结构一样. 与结构一样,枚举是值类型,因此直接存储它们的 ...

  4. Spring AOP介绍

    1.介绍 AOP(面向切面编程)对OOP(面向对象编程)是一种补充,它提供了另一种程序结构的思路.OOP的模块单元是class,而AOP的模块单元是aspect.Spring中一个关键的组件是AOP框 ...

  5. 【HDU 2063】过山车(二分图最大匹配模板题)

    题面 RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐.但是,每 ...

  6. [Luogu3066][USACO12DEC]逃跑的BarnRunning Away From…

    题面 题目描述 给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于等于l的点有多少个. 输入格式: Line 1: 2 integers, N and L (1 <= N <= 2 ...

  7. iOS开发--XMPPFramework--框架的导入(二)

    创了一个XMPP即时通讯交流群140147825,欢迎大家来交流~我们是一起写代码的弟兄~ xmpp协议开发即时通讯,最常用的就是XMPPFramework. 第一种方法,是直接拖进项目 1.可以下载 ...

  8. angular路由详解六(路由守卫)

    路由守卫 CanActivate: 处理导航到某个路由的情况. CanDeactivate:处理从当前路由离开的情况. Resole:在路由激活之前获取路由数据. 1.CanActivate: 处理导 ...

  9. 【Unity与23种设计模式】命令模式(Command)

    GoF中定义: "将请求封装成为对象,让你可以将客户端的不同请求参数化,并配合队列.记录.复原等方法来执行请求的操作." 实现命令模式的标准在于: 当请求被对象化后,对于请求对象是 ...

  10. 开源自己用python封装的一个Windows GUI(UI Automation)自动化工具,支持MFC,Windows Forms,WPF,Metro,Qt

    首先,大家可以看下这个链接 Windows GUI自动化测试技术的比较和展望 . 这篇文章介绍了Windows中GUI自动化的三种技术:Windows API, MSAA - Microsoft Ac ...