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

在上一篇中linux进程间通信:POSIX 消息队列我们知道消息队列中在消息个数达到了队列所能承载的上限,就会发生消息的写阻塞。
阻塞式的通信影响系统效率,进程之间在通信收到阻塞时并不能去做其他事情,而是一直处于阻塞状态。

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

  • 函数头文件#include <mqueue.h>
  • 函数使用: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 thread
                          notification (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<stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <signal.h>
#include <string.h>

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 \n");
        _exit(-1);
    }
    printf("read %ld bytes: %s\n",(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 \n");
        _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 \n", count ++);
        sleep(1);
    }
    
    mq_close(mq_id);
    return 0;
}

mq_snd.c同步写

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <string.h>

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\n");	
		_exit(-1);
	}
	
	//持续向消息队列中每隔两秒写入数据
	while(1) {
		if (mq_send(mq_id, "hello world", sizeof("hello world"), 1) == -1) {
			printf("mq_send failed \n");
			_exit(-1);
		}
		printf("msg send success -----\n");
		sleep(2);
	}
	return 0;
}

编译以上两个文件:gcc mq_notify.c -o mq_notify -lrt gcc mq_snd.c -o send -lrt
输出如下:
在这里插入图片描述
我们可以看到异步读并不会受消息队列为空的影响,即使消息队列为空,异步读进程仍然继续处理自己的事情;当同步写进程运行的时候,异步读进程收到一个使用mq_id注册的信号,开始执行信号回调函数,函数执行完,异步读进程继续处理自己的事情,直到再次收到相同的信号从而再次执行回调函数中的读消息队列。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
gear-lib通用的C基础库,包含很多牛逼的库源码,可以编译后使用集成到自己项目中,全部用POSIX C实现,目标是为了跨平台兼容 linux, windows, android, ios. * 适用于物联网,嵌入式,以及网络服务开发等场景 ![struct](https://github.com/gozfree/gear- lib/blob/master/gear-lib.png) 该基础库包含以下库: ## 数据结构 | | | |--|--| | libdict: 哈希字典 | libhash: linux内核原生哈希库 | | libringbuffer: 循环 缓冲 | libqueue: 数据队列 | | librbtree: 内核rbtree | libsort: | | libvector: 容器库 | libdarray: 动态数组 | ## 网络库 | | | |--|--| | librtsp: RTSP协议,适合IPCamera和NVR开发 | librtmpc: RTMP协议,适合推流直播 | | libsock: Socket封装 | librpc: 远程过程调 用库 | | libipc: 进程间通信 | libp2p: p2p穿透传输 | | libhomekit: Apple homekit协议库 | | ## 异步 | | | |--|--| | libgevent: 事件驱 动 | libthread: 线程 | | libworkq: 工作队列 | | ## I/O | | | |--|--| | libbase64: Base64/32 编解码 | libconfig: 配置文件库 | liblog: 日志库 | libfile: 文件操作库 | | libstrex: | libsubmask: 网络地址翻译 | ## 多媒体 | | | |--|--| | libuvc: USB摄像头库 | libmp4: MP4录制解析库 | | libjpeg-ex: | libmedia-io: 音频视频格式定义 | ## 系统抽象层 | libposix: windows/rtos/ios平 台posix适配库 | | libdebug: 调试辅助库 | libhal: 硬件抽象层 | | libplugin: 动态加载库 | libtime: 时间库 | | libfsm: 有限状态机

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值