概念: 进程彼此之间可以通过IPC消息进行通信。进程产生的每条消息都被发送到一个IPC消息队列中,这条消息一直存放在队列中,直到另一个进程将其读走为止。

优点:可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题;消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。而且,每个数据块被认为含有一个类型,接收进程可以独立地接收含有不同类型值的数据块。

缺点:每个数据块有一个最大长度的限制;系统中所有消息队列所包含的全部数据块的总长度也有一个上限。

基本原理: 消息是由固定大小的首部和可变长度的正文组成的;可以使用一个整数值标识消息,这就允许进程有选择的从消息队列中获取消息。只要进程从IPC消息队列中读出一条消息,内核就把这条消息删除;因此,一个进程只能接收一条给定的消息。当消息队列满时,则试图让新消息入队的进程可能被阻塞。当消息队列为空时,则接收进程甚至会被阻塞。

代码示例

发送信息的程序的源文件msgsend.c的源代码为:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h> #define MAX_TEXT 512
struct msg_st
{
long int msg_type;
char text[MAX_TEXT];
}; int main()
{
int running = ;
struct msg_st data;
char buffer[BUFSIZ];
int msgid = -; //建立消息队列
msgid = msgget((key_t), | IPC_CREAT);
if(msgid == -)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
} //向消息队列中写消息,直到写入end
while(running)
{
//输入数据
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
data.msg_type = ; //注意2, 用来设置发送的信息的信息类型,即其发送的信息的类型为1
strcpy(data.text, buffer);
//向队列发送数据
if(msgsnd(msgid, (void*)&data, MAX_TEXT, ) == -)
{
fprintf(stderr, "msgsnd failed\n");
exit(EXIT_FAILURE);
}
//输入end结束输入
if(strncmp(buffer, "end", ) == )
running = ;
sleep();
}
exit(EXIT_SUCCESS);
}

接收信息的程序源文件为msgreceive.c的源代码为:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h> struct msg_st
{
long int msg_type;
char text[BUFSIZ];
}; int main()
{
int running = ;
int msgid = -;
struct msg_st data;
long int msgtype = ; //注意1,值为0表示获取队列中第一个可用的消息 //建立消息队列
msgid = msgget((key_t), | IPC_CREAT);
if(msgid == -)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
//从队列中获取消息,直到遇到end消息为止
while(running)
{
if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, ) == -)
{
fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s\n",data.text);
//遇到end结束
if(strncmp(data.text, "end", ) == )
running = ;
}
//删除消息队列
if(msgctl(msgid, IPC_RMID, ) == -)
{
fprintf(stderr, "msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

如果把注意1,即msgreceive.c文件main函数中的语句由long int msgtype = 0;改变为long int msgtype = 2;会发生什么情况,msgreceive将不能接收到程序msgsend发送的信息。因为在调用msgrcv函数时,如果msgtype(第四个参数)大于零,则将只获取具有相同消息类型的第一个消息,修改后获取的消息类型为2,而msgsend发送的消息类型为1,所以不能被msgreceive程序接收。
msgreceive如果没有接收到信息和输出,而且当msgsend输入end结束后,msgreceive也不会结束,通过jobs命令我们可以看到它还在后台运行着。

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

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

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

  2. 深入剖析 RabbitMQ —— Spring 框架下实现 AMQP 高级消息队列协议

    前言 消息队列在现今数据量超大,并发量超高的系统中是十分常用的.本文将会对现时最常用到的几款消息队列框架 ActiveMQ.RabbitMQ.Kafka 进行分析对比.详细介绍 RabbitMQ 在 ...

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

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

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

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

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

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

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

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

  7. Linux进程间通信之消息队列

    本文依据以下思路展开,首先从宏观上阐述消息队列的机制,然后以具体代码为例进一步阐述该机制,最后试着畅想一下该通信机制潜在的应用. 消息队列是在两个不相关进程间传递数据的一种简单.高效方式,她独立于发送 ...

  8. linux 进程间通信之 消息队列

    消息队列就是一个消息的链表. 能够把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程能够向中依照一定的规则加入新消息.有读权限的进程则能够读走消息. 读走就没有了.消息队列是 ...

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

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

随机推荐

  1. 47、[源码]-Spring容器创建-初始化MessageSource

    47.[源码]-Spring容器创建-初始化MessageSource 7.initMessageSource();初始化MessageSource组件(做国际化功能:消息绑定,消息解析): 获取Be ...

  2. fdisk分区命令

    fdisk是Linux系统中最常用的分区工具,通过这个命令也可以查看系统中所有可用的分区,但是这个命令只支持MBR的分区表(这句话应该只对某些系统,CentOS7-1810适用,Debian9.5和o ...

  3. vue 组件的通信方式(完整版)

    几种通信方式无外乎以下几种: Prop(常用) $emit (组件封装用的较多) .sync语法糖 (较少) $attrs & $listeners (组件封装用的较多) provide &a ...

  4. Invalid Component definition:header

    主要是header不是字符串,而是变量

  5. vue-qr生成下载二维码

    安装vue-qr npm install vue-qr --save 生成二维码实列 <vue-qr ref="Qrcode" :text="qrCodeConfi ...

  6. Lucene4.2源码解析之fdt和fdx文件的读写(续)——fdx文件存储一个个的Block,每个Block管理着一批Chunk,通过docID读取到document需要完成Segment、Block、Chunk、document四级查询,引入了LZ4算法对fdt的chunk docs进行了实时压缩/解压

    2       索引读取阶段 当希望通过一个DocId得到Doc的全部内容,那么就需要对fdx/fdt文件进行读操作了.具体的代码在CompressingStoredFieldsReader类里面.与 ...

  7. 2018-2019-2 20165114《网络对抗技术》Exp7 网络欺诈防范

    Exp7 网络欺诈防范 目录 一.实验内容 二.基础问题回答 (1)通常在什么场景下容易受到DNS spoof攻击 (2)在日常生活工作中如何防范以上两攻击方法 三.实践过程记录 3.1简单应用SET ...

  8. Python_BDD概念

    BDD概念 全称 Behavior-driven development 中文 行为驱动开发 概念 是敏捷软件开发技术的一种,鼓励各方人员在一个软件项目里交流合作,包括开发人员.测试人员和非技术人员或 ...

  9. 解决用root用户及密码可以直接登陆某LINUX系统,但是用ssh登陆,系统却总是提示密码不对

    引用 vi /etc/ssh/sshd_config 将PermitRootLogin项改为yes service sshd restart 重启sshd服务即可

  10. 【Java】线程需要独立的Connection,那对已经配好session的Spring/Mabatis工程该怎么办?

    方法一:让线程从配置中取DataSource. 方法二:从配置中取出SessionFactory,然后交给线程去创建session和Connection,举例如下: // Get Session Fa ...