日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

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

發布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 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<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注冊的信號,開始執行信號回調函數,函數執行完,異步讀進程繼續處理自己的事情,直到再次收到相同的信號從而再次執行回調函數中的讀消息隊列。

總結

以上是生活随笔為你收集整理的linux进程间通信:POSIX 消息队列 ----异步通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。