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

歡迎訪問 生活随笔!

生活随笔

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

生活经验

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

發布時間:2023/11/27 生活经验 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux进程间通信:POSIX 消息队列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 基本介紹
        • 相關編程接口
        • 編程實例
          • 消息隊列通信實例
          • 消息隊列屬性設置實例

基本介紹

關于消息隊列的基本介紹,前面在學習system V的消息隊列時已經有過了解,linux進程間通信:system V消息隊列

  1. 支持不同進程之間以消息(messages)的形式進行數據交換,消息能夠擁有自己的標識,且內核使用鏈表方式進行消息管理。
  2. 進程之間的通信角色為:發送者和接受者
    發送者:
    a. 獲取消息隊列的ID(key或者msgid)
    b. 將數據放入一個帶有標識的消息結構體,發送到消息隊列
    接受者:
    a. 獲取消息隊列的ID
    b. 指定標識的消息從消息隊列中讀出,然后進一步后續處理
  3. 支持不同的進程標記不同的消息優先級(0,1,2…),并由內核態維護對應消息類型的鏈表。
  4. 內核態的0號消息類型維護了一個鏈表,用來保存按照時間順序加入的消息

相關編程接口

  • mq_open :創建或打開一個消息隊列
  • mq_send :向消息隊列寫入一條消息
  • mq_receive :從消息隊列中讀取一條消息
  • mq_close :關閉進程打開的消息隊列
  • mq_unlink :刪除一個消息隊列
  • mq_setattr :設置消息隊列的一些額外屬性
  • mq_getattr :獲取消息隊列的一些額外屬性
  • mq_notify :異步通知
  1. 創建或打開一個消息隊列
    a. 頭文件 <mqueue.h> <sys/stat.h> <fcntl.h>
    b. 函數使用:
    mqd_t mq_open(const char *name, int oflag);
    mqd_t mq_open(const char *name, int oflag, mode_t mode,struct mq_attr *attr);
    c. 函數功能:創建一個新的POSIX消息隊列或者打開一個已存在的消息隊列。且消息隊列是由name標識
    d. 函數參數:

    • name 用來標識需要創建或者打開的ipc對象
    • oflag O_CREAT/O_RDONLY/O_WRONLY/O_RDWR/O_EXCL/O_NOBLOCK
      標記使用什么樣的方式打開ipc對象
    • mode 位掩碼,用來設置權限 8進制
    • attr 設置消息隊列的屬性,若為NULL,使用默認屬性,linux 3.5以后版本也可以通過/proc查看設置
      主要數據結構如下:
       struct mq_attr {long mq_flags;       /* Flags (ignored for mq_open()) */long mq_maxmsg;      /* Max. # of messages on queue */long mq_msgsize;     /* Max. message size (bytes) */long mq_curmsgs;     /* # of messages currently in queue(ignored for mq_open()) */
      };
      

    e. 函數返回值
    成功:返回消息隊列對象的描述符
    失敗:返回-1,并設置errno

  2. 關閉一個消息隊列
    a. 頭文件 :#include <mqueue.h>
    b. 函數使用:int mq_close(mqd_t mqdes);
    c. 函數功能:關閉一個描述符為mqdes的消息隊列
    d. 返回值:
    成功:返回0
    失敗:返回-1
    e. 注意:POSIX消息隊列在進程終止或者執行execve()時會自動關閉

  3. 刪除消息隊列
    a. 頭文件: #include <mqueue.h>
    b. 函數使用: int mq_unlink(const char *name);
    c. 函數功能:刪除通過name標識的消息隊列;在所有進程使用完該隊列之后銷毀該隊列;若打開該隊列的所有進程都已關閉,則立即刪除
    d. 返回值:
    成功:0
    失敗:-1

  4. 向消息隊列中寫入消息
    a. 頭文件: #include <mqueue.h>
    b. 函數使用: int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
    c. 函數功能:將msg_ptr所指向的緩沖區中的消息內容添加到描述符mqdes所引用的消息隊列中
    d. 函數參數:

    • mqdes :消息隊列描述符
    • msg_ptr: 指向存放消息的緩沖區指針
    • msg_len: 消息的長度[10,8192]
    • msg_prio: 消息隊列中按優先級排序,設置為0標識無需優先級;該參數為POSIX消息隊列和system V消息隊列的差異,即POSIX是通過優先級來區分消息,system V是通過消息類型來區分消息

    e. 返回值
    成功:0
    失敗:-1

  5. 從消息隊列中接收數據
    a. 頭文件: #include <mqueue.h>
    b. 函數使用: ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
    c. 函數功能:默認從mqdes引用的消息隊列中刪除一條優先級最高、存放時間最長的消息;并將刪除的消息保存在msg_ptr;
    這里如果接收時指定優先級,可以讀取指定優先級的消息,并存放在msg_ptr
    d. 函數參數:

    • mqdes :消息隊列描述符
    • msg_ptr: 指向存放消息的緩沖區指針
    • msg_len: 消息的長度[10,8192]
    • msg_prio: 消息隊列中按優先級排序,設置為0標識無需優先級;

    e. 返回值
    成功:消息接收的字節數
    失敗:-1

  6. 獲取/設置消息隊列的屬性信息
    a. 頭文件 #include <mqueue.h>
    b. 函數使用:
    int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
    int mq_setattr(mqd_t mqdes, const struct mq_attr *newattr, struct mq_attr *oldattr);
    c. 函數功能:獲取或者修改一個由mqdes標識的消息隊列的屬性信息
    d. 函數參數:

    • mqdes 消息隊列的唯一標識
    • newattr 設置修改后的mq_attr結構體類型的屬性信息
    • oldattr 修改前的屬性信息,如果當前參數為NULL,則默認設置從mq_getattr中獲取到的屬性信息

    關于消息隊列的屬性設置如下兩種方式:

    • 通過proc文件系統
      echo num > /proc/sys/fs/mqueue/queues_max
      echo num > /proc/sys/fs/mqueue/msg_max
      echo num > /proc/sys/fs/mqueue/msgsize_max
    • 通過POSIX系統調用接口設置
      mq_setattr 僅能設置mq_flags
      mq_open 僅設置 mq_maxmsgmq_msgsize

編程實例

最終創建的POSIX消息隊列的實例存放在/dev/mqueue路徑下

消息隊列通信實例

mq_demo.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>#include <mqueue.h>int main()
{mqd_t mq_id;//創建一個消息隊列if ((mq_id = mq_open("/posix_msgqueue",O_RDWR | O_CREAT, 0666, NULL)) == -1) {printf("mq_open failed \n");_exit(-1);}struct mq_attr mq;//獲取消息隊列的各個屬性if (mq_getattr(mq_id ,&mq)  == -1 ){_exit(-1);}printf("mq_flags %ld\n",mq.mq_flags); //mq_open默認將當前屬性忽略,則一般為0printf("mq_maxmsg %ld\n",mq.mq_maxmsg); //消息隊列可以接收的最大消息容量為10個,當達到10個,則當前進程阻塞printf("mq_msgsize %ld\n",mq.mq_msgsize); //每個消最大容量printf("mq_curmsgs %ld\n",mq.mq_curmsgs);int ret;if ((ret = fork()) == -1) {printf("fork failed \n");_exit(-1);}//創建子進程用來接收消息隊列的信息,且接收的優先級為NULL,即默認接收優先級最高且存放時間最長的消息else if (ret == 0 ) {char msg_buf[mq.mq_msgsize];memset (msg_buf , 0 , mq.mq_msgsize);while(1) {if (mq_receive(mq_id,msg_buf,mq.mq_msgsize,NULL) == -1) {printf("mq_receive failed \n");_exit(-1);}printf("child process receive msg :%s \n",msg_buf);sleep(1);}}else {while(1) {//父進程用來發送消息隊列的信息,并設置發送的消息優先級為1//如果父進程發送多個優先級消息,子進程指定具體的一個優先級消息進行接收即可if (mq_send(mq_id,"hello world",sizeof("hello world"),1) == -1) {printf("mq_send failed\n");_exit(-1);}printf("parent process :send msg to mqueue success\n");sleep(1);}}//關閉當前進程對消息隊列 mq_id的引用mq_close(mq_id);sleep(5);//引用計數為0時,刪除當前進程創建的消息隊列if(mq_unlink("/posix_msgqueue") == -1) {printf("mq_unlink failed\n");_exit(-1);}return 0;
}

輸出如下:

消息隊列屬性設置實例

我們知道如下三個參數,POSIX消息隊列默認的屬性值為

mq_flags = 0
mq_maxmsg = 10
mq_msgsize = 8192

通過如下代碼可以分別看到mq_openmq_setattr對屬性值的設置

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <string.h>int main () {mqd_t mq_id;/*使用mq_open同時對三個參數更改*/struct mq_attr addr;addr.mq_flags = O_NONBLOCK;addr.mq_maxmsg = 5;addr.mq_msgsize = 4096;//將需要設置對屬性參數設置為addrmq_id = mq_open("/notify",O_WRONLY | O_CREAT, 0666, &addr);if (mq_id == -1) {printf("mq_open failed\n");	_exit(-1);}if (mq_getattr(mq_id,&addr) == -1) {printf("mq_getattr failed\n");_exit(-1);}//打印最終對設置結果printf("mq_open set mq_flags = %ld\n",addr.mq_flags);printf("mq_open set mq_maxmsg = %ld\n", addr.mq_maxmsg);printf("mq_open set mq_msgsize = %ld\n", addr.mq_msgsize);/*同樣對所有的屬性參數,使用mq_setattr進行設置*/struct mq_attr attr;attr.mq_flags = O_NONBLOCK;attr.mq_maxmsg = 8;attr.mq_msgsize = 2048;if(mq_setattr(mq_id,&attr,NULL) == -1) {printf("mq_set attr failed \n");_exit(-1);}if (mq_getattr(mq_id,&attr) == -1) {printf("mq_getattr failed\n");_exit(-1);}printf("mq_setattr set mq_flags = %ld\n",attr.mq_flags);printf("mq_setattr set mq_maxmsg = %ld\n", attr.mq_maxmsg);printf("mq_setattr set mq_msgsize = %ld\n", attr.mq_msgsize);return 0;
}

輸出結果如下:

mq_open set mq_flags = 0
mq_open set mq_maxmsg = 5
mq_open set mq_msgsize = 4096
mq_setattr set mq_flags = 2048
mq_setattr set mq_maxmsg = 5
mq_setattr set mq_msgsize = 4096

可見,mq_flags參數只有mq_setattr系統調用能夠成功設置
mq_maxmsg和mq_msgsize對屬性僅能由mq_opn系統調用設置成功

總結

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

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