首页 > linux进程间通信:POSIX 消息队列 ----异步通信

linux进程间通信:POSIX 消息队列 ----异步通信

在上一篇中linux进程间通信:POSIX 消息队列我们知道消息队列中在消息个数达到了队列所能承载的上限,就会发生消息的写阻塞。

阻塞式的通信影响系统效率,进程之间在通信收到阻塞时并不能去做其他事情,而是一直处于阻塞状态。

为了避免出现这样的低效问题,POSIX消息队列推出如下接口实现异步通信机制

  • 函数头文件#include
  • 函数使用:int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
  • 函数功能:允许调用者注册或者注销一个异步信号,当进行消息传输的时候利用该信号可以执行异步操作

    具体如下:

    当一个空的消息队列接收到消息时给进程发送一个通知;

    当执行完相关处理,通知机制结束,可以重新调用mq_notify注册
  • 函数参数:

    mqdes: 消息队列的id

    sevp: 通知方式设置

    其中关于结构体sigevent描述如下
    struct sigevent { int          sigev_notify; /* Notification method 通知的方式*/ int          sigev_signo;  /* Notification signal 通知发送的信号*/union sigval sigev_value;  /* Data passed with notification */void       (*sigev_notify_function) (union sigval);/* Function used for threadnotification (SIGEV_THREAD) */void        *sigev_notify_attributes;/* Attributes for notification thread(SIGEV_THREAD) */pid_t        sigev_notify_thread_id;/* ID of thread to signal (SIGEV_THREAD_ID) */
    };
    
    sigev_notify 通知的方式如下几种:
    • SIGEV_NONE 有通知时什么也不做
    • SIGEV_SIGNAL 给进程发送一个信号来通知进程
    • SIGEV_THREAD/SIGEV_THREAD_ID

代码演示如下:

mq_notify.c 异步读

#include
#include 
#include 
#include 
#include 
#include mqd_t mq_id;
char buf[8192];
struct sigevent sigev;static void signal_handler(int signo) { ssize_t receive_len;//再次进行消息队列和异步通知方式注册的结构体进行绑定mq_notify(mq_id, &sigev);//尝试从mq_id中获取消息receive_len = mq_receive(mq_id, buf,8192, NULL);if (receive_len == -1) { printf("mq_receive failed 
");_exit(-1);}printf("read %ld bytes: %s
",(long) receive_len, buf);return ;
}int main() { //创建消息队列mq_id = mq_open("/notify",O_RDONLY | O_CREAT, 0666, NULL);if (mq_id == -1) { printf("mq_open failed 
");_exit(-1);}//信号处理逻辑,注册SIGUSR1用户信号,并设置回调函数signal(SIGUSR1, signal_handler);sigev.sigev_notify = SIGEV_SIGNAL;sigev.sigev_signo = SIGUSR1;//将消息队列的id和注册的异步通信结构体进行绑定mq_notify(mq_id, &sigev);int count = 0;while(1) { printf("while loop %d 
", count ++);sleep(1);}mq_close(mq_id);return 0;
}

mq_snd.c同步写

#include 
#include 
#include 
#include 
#include int main () { mqd_t mq_id;//打开创建好的消息队列mq_id = mq_open("/notify",O_WRONLY | O_CREAT, 0666, NULL);if (mq_id == -1) { printf("mq_open failed
");	_exit(-1);}//持续向消息队列中每隔两秒写入数据while(1) { if (mq_send(mq_id, "hello world", sizeof("hello world"), 1) == -1) { printf("mq_send failed 
");_exit(-1);}printf("msg send success -----
");sleep(2);}return 0;
}

编译以上两个文件:gcc mq_notify.c -o mq_notify -lrt gcc mq_snd.c -o send -lrt

输出如下:

在这里插入图片描述

我们可以看到异步读并不会受消息队列为空的影响,即使消息队列为空,异步读进程仍然继续处理自己的事情;当同步写进程运行的时候,异步读进程收到一个使用mq_id注册的信号,开始执行信号回调函数,函数执行完,异步读进程继续处理自己的事情,直到再次收到相同的信号从而再次执行回调函数中的读消息队列。

更多相关:

  • 文章目录基本介绍相关编程接口编程实例消息队列通信实例消息队列属性设置实例 基本介绍 关于消息队列的基本介绍,前面在学习system V的消息队列时已经有过了解,linux进程间通信:system V消息队列 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用链表方式进行消息管理...

  • 首先对微擎的工作原理做简单描述, 微擎使用规则和模块的机制来处理公众平台的请求数据并返回响应的结果.执行流程描述为: 粉丝用户与公众号码进行对话或交互, 而后公众平台将粉丝用户的请求消息(当前包括: 文本, 图片, 位置, 链接, 事件. 请参阅消息类型)传递给微擎系统, 微擎系统按照消息类型和对应的公众号所设定的规则列表匹配到合适的...

  • 消息队列的使用场景以下介绍消息队列在实际应用常用的使用场景。异步处理、应用解耦、流量削锋和消息通讯四个场景。1】异步处理:场景说明:用户注册后,需要发注册邮件和注册短信。引入消息队列后架构如下:用户的响应时间=注册信息写入数据库的时间,例如50毫秒。发注册邮箱、发注册短信写入消息队列后,直接返回客户端,因写入消息队列的速度很快,基...

  • 下面是我凭记忆想到的几个题目,有需要的同学就拿去吧,我也算做了点善事. 中体骏彩C++笔试题 2013-11-18 1.指针的含义是:B A.名字 B.地址 C.名称 D.符号 2.给出下面的程序输出: #include #include #include ...

  • 双端通信描述 利用消息队列针对发送接受消息的类型唯一性 进行多个客户端之间消息传递,而不需要server端进行消息转发。 同时消息队列的读阻塞和写阻塞特性(消息队列中已经写入数据,如果再不读出来,则无法再次写入)让消息队列的实现过程只能如下: 客户端1的父进程用来处理类型1的消息写,子进程处理类型2的消息读客户端2的父进程处理类型...

  • 文章目录基本介绍编程接口代码实例消息队列的发送和接收消息队列中的消息对象的属性控制 基本介绍 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用链表方式进行消息管理。进程之间的通信角色为:发送者和接受者 发送者: a. 获取消息队列的ID(key或者msgid) b. 将数据放入...

  •     先吐为敬!   最近心血来潮研究nodejs如何完成微信支付功能,结果网上一搜索,一大堆“代码拷贝党”、“留一手”、“缺斤少两”、“不说人话”、“自己都没跑通还出来发blog”、“各种缺少依赖包”、“各种注释都没有”、“自己都不知道在写什么”的程序大神纷纷为了增加自己博客一个帖子的名额而发布了各种千奇百�...

  • 阅读ceph源码过程中需要明确当前操作是由哪个线程发出,此时需要根据线程id来确认线程名称 C++获取线程id是通过系统调用来直接获取 函数描述 头文件: 函数名称:syscall(SYS_gettid) 该函数直接返回了一个pid_t int类型的数字,即为当前线程id 此外函数pthread_s...

  • 面试题 分库分表之后,id 主键如何处理? 面试官心理分析 其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持。所以这都是你实际生产环境中必须考虑的问题。 面试题剖析 基于数据库的实现方案 数据库自增 id 这个就是说你的...

  • ORM操作    单表、一对多表操作 1 from django.db import models 2 3 4 class UserGroup(models.Model): 5 title = models.CharField(max_length=32) 6 7 8 class UserInfo(m...

  • 建立如下表: 建表语句: class表创建语句 create table class(cid int not null auto_increment primary key, caption varchar(32) not null)engine=innodb default charset=utf8;student表创建语句 c...