1. 程式人生 > >程序間通訊筆記(3)—POSIX訊息佇列

程序間通訊筆記(3)—POSIX訊息佇列

POSIX 訊息佇列

1.概述

訊息佇列可認為是一個訊息連結串列,頭訊息指定當前佇列的兩個屬性:佇列中允許的最大訊息數和每個訊息的最大大小。而每個訊息本身除了資料之外還包括優先順序和資料長度等內容。

1.1POSIX訊息佇列和SystemV訊息佇列的區別

1.對於Posix訊息佇列讀操作總是返回最高優先順序的最早訊息,而SystemV則可以返回任意指定優先順序的訊息。
2.當往一個空佇列放置訊息時,Posix訊息佇列允許產生一個訊號或者啟動一個執行緒,SystemV不具備這樣的機制。

1.2Posix訊息佇列資料結構

設想訊息佇列是一個連結串列,連結串列的頭節點包含了最大訊息數mq_maxmsg

和每個訊息的最大資料量mq_msgsize兩個屬性,資料節點則除了訊息本身還有優先順序,長度等欄位資訊。如圖:

這裡寫圖片描述

2.POSIX訊息佇列程式設計

POSIX 訊息佇列的IPC物件是以檔案的方式存在於虛擬檔案系統中,這些檔案可以在終端使用ls命令檢視,和使用rm命令刪除。當我們要操作這些訊息佇列時,需要掛在訊息佇列檔案系統:

su
Password:
# mkdir /dev/mqueue
# mount -t mqueue none /dev/mqueue
$exit
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h> /* For mode constants */ #include <mqueue.h> 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); Link with -lrt.

mq_open()建立或者開啟一個已經存在的POSIX 訊息佇列,這些訊息佇列用name引數來標識,一般是”/xxxx”的形式,建立成功後,訊息佇列將存在掛載在檔案系統上的目錄,例如/dev/mqueue

#include <mqueue.h>

int mq_close(mqd_t mqdes);

Link with -lrt.

close()函式的功能類似,關閉描述符,但是訊息佇列仍然存在,要刪除訊息佇列,需要使用mq_unlink()

#include <mqueue.h>

int mq_unlink(const char *name);

Link with -lrt

2.2 訊息佇列屬性

每個訊息佇列有四個屬性,如下結構體所示:

struct mq_attr {
    long mq_flags;       /* Flags: 0 or O_NONBLOCK */
    long mq_maxmsg;      /* Max number of messages on queue */
    long mq_msgsize;     /* Max size of a message (in bytes) */
    long mq_curmsgs;     /*numbers of messages currently in queue */
};

這些屬性的預設值可以通過下述方式檢視:

cat /proc/sys/fs/mqueue/msg_max         // 對應mq_maxmsg 預設10
cat /proc/sys/fs/mqueue/msgsize_max     //對應mq_msgsize 預設8192
cat /proc/sys/fs/mqueue/queues_max      //最大訊息佇列數 預設256

也可以通過mq_setattrmq_getattr這兩個函式來設定和獲取狀態:

#include <mqueue.h>

int mq_getattr(mqd_t mqdes, struct mq_attr *attr);

int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);

Link with -lrt.

2.3 mq_send和mq_receive函式

#include <mqueue.h>
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int  msg_prio);
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

writeread類似,不同的是,mq_send在傳送訊息時最後一個引數作為訊息的優先順序,mq_receive最後一個引數指標用來返回訊息優先順序。如果優先順序並不需要,那麼將unsigned int msg_prio設定為0,unsigned int *msg_prio設定為NULL。

2.4完整測試程式碼

簡單的讀寫,寫入端依次寫入優先順序不同的五個訊息,讀入端依次讀出,根據POSIX訊息佇列的定義,讀出順序將是依次讀出優先順序高的最早訊息。

寫入端

//psxmq_send.c

#include <mqueue.h>
#include <stdbool.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>    
#include <time.h>   
#include <errno.h>
#include <string.h>

#define MAXSIZE 1024
int main(int argc,char**argv)
{
    if(argc!=2)
    {
    printf("Usage: %s /mqname \r\n",argv[0]);
    return -1;
    }
    char Msg[MAXSIZE]="Hello World";
    char *name = argv[1];
    int flags = O_RDWR | O_CREAT | O_EXCL ;
    mode_t mode = S_IRUSR | S_IWUSR| S_IRGRP |S_IROTH;
    //set mq_attr
    struct mq_attr attr;
    attr.mq_flags=0;
    attr.mq_maxmsg=10;
    attr.mq_msgsize=sizeof(Msg);
    attr.mq_curmsgs=0;

    mqd_t mqid = mq_open(name,flags,mode,&attr);
    if(mqid==-1)
    {
        printf("error %s (%d)\r\n",strerror(errno),errno);
        return -1;
    }
    int i;
    for(i=0;i<5;i++)
    {
        if(mq_send(mqid,Msg,strlen(Msg),i)==-1)
        {
            perror("mq_send error");
            return -1;
        }
    }
    mq_close(mqid);
    return 0;
}

讀出端

//psxmq_recv.c

#include <mqueue.h>
#include <stdbool.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>    
#include <time.h>      
#include <errno.h>
#include <string.h>

int main(int argc,char**argv)
{
    if(argc !=2)
    {
        printf("Usage: %s /mqname \r\n",argv[0]);
        return -1;
    }
    const int MAXSIZE =1024;
    char RecvBuff[MAXSIZE];
    int prio;
    ssize_t n;
    char* name  = argv[1];
    int   flags = O_RDONLY;

    memset(RecvBuff,0x00,sizeof(RecvBuff));
    mqd_t mqid = mq_open(name, flags);

    struct mq_attr attr;
    if(mqid==-1)
    {
        printf("error %s (%d)\r\n",strerror(errno),errno);
        return -1;
    }
    while(true)
    {
        if(mq_getattr(mqid,&attr)==-1)
        {
            printf("get attr error\r\n");
            break;
        }
        if(attr.mq_curmsgs==(long)0)
        {
            printf("no messages in queue\r\n");
            break;
        }

        if((n=mq_receive(mqid,RecvBuff,sizeof(RecvBuff),&prio))==-1)
        {
            perror("mq_receive error");
            return -1;
        }
        printf("read %ld bytes\r\n",(long)n);
        printf("prio is %d\r\n",prio);
        printf("%s \r\n",RecvBuff);
    }
    mq_close(mqid);
    mq_unlink(name);
    return 0;
}

Makefile

PROGS =Send Recv
CLEANFILES = core core.* *.core *.o temp.* *.out typescript* \
        *.lc *.lh *.bsdi *.sparc *.uw

all :${PROGS}


CFLAGS+=-g  
LIBS+=-lrt

Recv: psxmq_recv.o
    ${CC} ${CFLAGS} ${LIBPATH} $^  -o [email protected] ${LIBS}  
    @rm *.o

Send: psxmq_send.o
    ${CC} ${CFLAGS} ${LIBPATH} $^ -o [email protected]   ${LIBS}  
    @rm *.o

clean:
    rm -f ${PROGS} ${CLEANFILES}

3.參考

相關推薦

程序通訊筆記3POSIX訊息佇列

POSIX 訊息佇列 1.概述 訊息佇列可認為是一個訊息連結串列,頭訊息指定當前佇列的兩個屬性:佇列中允許的最大訊息數和每個訊息的最大大小。而每個訊息本身除了資料之外還包括優先順序和資料長度等內容。 1.1POSIX訊息佇列和SystemV訊息佇列的區

程序通訊筆記7—SystemV訊號量

1.概述 SystemV訊號量並不如Posix訊號量那樣“好用”,但相比之下它的年代更加久遠,但是SystemV使用的卻更加廣泛(尤其是在老系統中)。在學習Posix訊號量的時候,已經大概清楚了二值訊號量和計數訊號量是什麼東西。在接觸SystemV訊號量之後,

Android安全/開發基礎--6--程序通訊機制IPC

6-1、多程序 1、多程序分為兩種: 第一種情況是一個應用因為某些原因自身需要採用多執行緒模式來實現。 另一種情況是當前應用需要向其他應用獲取資料。 2、Android中的多程序模式: 通過給四大元件指定android:process屬性,可以開啟多程序模式,使

Nginx原始碼分析與實踐---程序通訊機制訊號

在前面我們分析了nginx程序間通訊機制的共享記憶體和套接字。這次我們分析剩下一種程序間通訊機制---訊號。 首先要區分訊號和訊號量:訊號是用於程序間通訊的機制,而訊號量是用於保證共享資源不被併發訪問的機制,如可使用訊號量作為互斥鎖實現多程序下對共享資源的同步。 1.nginx中什

程序通訊-管道PIPE和有名管道FIFO

1.2有名管道的建立 該函式的第一個引數是一個普通的路勁名,也就是建立後FIFO的名字。第二個引數與開啟普通檔案的open()函式中的mode引數相同。如果mkfifo的一個引數是一個已經存在路勁名時,會返回EEXIST錯誤,所以一般典型的呼叫程式碼首先會檢查是否返回該錯誤,如果確實返回該錯誤,

android程序通訊Binder

最近在看程序間通訊方面的東西,在這裡粗略的的記錄一下自己看到的東西。 在android中實現程序間通訊用的都是Binder機制,Binder:貼上劑,個人感覺很形象,將各個程序貼上起來,實現程序之間資料的互動,拒絕了程序間的老死不相往來。本來程序就是互斥的,為的就是保持程序

Spark Streaming實時流處理筆記4—— 分散式訊息佇列Kafka

1 Kafka概述 和訊息系統類似 1.1 訊息中介軟體 生產者和消費者 1.2 Kafka 架構和概念 producer:生產者(生產饅頭) consumer:消費者(吃饅頭) broker:籃子 topic : 主題,給饅頭帶一個標籤,(

C++ 多執行緒框架3訊息佇列

之前,多執行緒一些基本的東西,包括執行緒建立,互斥鎖,訊號量,我們都已經封裝,下面來看看訊息佇列 我們儘量少用系統自帶的訊息佇列(比如Linux的sys/msgqueue),那樣移植性不是很強,我們希望的訊息佇列,在訊息打包和提取都是用的標準的C++資料結構,當然,

Linux程序通訊之訊號量(semaphore)、訊息佇列(Message Queue)和共享記憶體(Share Memory)

System V 程序通訊方式:訊號量(semaphore)、訊息佇列(Message Queue)和共享記憶體(Share Memory) 訊號量 訊號量(semaphore)實際是一個整數,它的值由多個程序進行測試(test)和設定(set)。就每個程序所關心的測試和

Linux程序通訊(IPC)程式設計實踐十二Posix訊息佇列--基本API的使用

posix訊息佇列與system v訊息佇列的差別: (1)對posix訊息佇列的讀總是返回最高優先順序的最早訊息,對system v訊息佇列的讀則可以返回任意指定優先順序的訊息。 (2)當往一個空佇列放置一個訊息時,posix訊息佇列允許產生一個訊號或啟動一個執行緒,

程序通訊機制管道、訊號、共享記憶體/訊號量/訊息佇列、執行緒通訊機制互斥鎖、條件變數、posix匿名訊號量

(1)系統中每個訊號量的資料結構(sem)struct sem {     int semval; /* 訊號量的當前值 */     unsigned short  semzcnt;  /* # waiting for zero */     unsigned short  semncnt;  /* # w

QT學習筆記3 我的第一個程序

9.png har 中文 gets 有一個 setw 通過 坐標 關系 今天,學習搭建一個空項目,了解程序是如何運行的。 (1)新建一個空項目   1、在創建完空項目之後,項目中只有一個空的項目文件( .pro)        2、然後需要在項目文件(.pro)中添加:

程序程序通訊 —— Queue佇列和Pipe管道

目錄 程序間通訊 佇列  概念介紹 方法介紹 程式碼例項 生產者消費者模型 JoinableQueue([maxsize])  管道(瞭解) 程序間通訊 IPC(Inter-Process Communication) 佇列&nbs

Linux高階程式設計9————程序通訊6訊號量

訊號量是是什麼? 訊號量是程序間通訊方式之一,用來實現程序間的同步與互斥。訊號量的原理是一種資料操作鎖的概念,它本身不具備資料交換的功能,而是通過控制其他通訊資源(如文字、外部裝置等)來實現程序間通訊。訊號量本身不具備資料傳輸的功能,他只是一種外部資源的標識。 訊號量的本質是:具有等待佇

Linux高階程式設計8————程序通訊4共享記憶體

共享記憶體是什麼? 因為程序之間是相互獨立的,他們有各自程序地址空間,那麼他們需要通訊時就要藉助核心來為他們建立橋樑,像之前我們瞭解的管道、訊息佇列就是核心做的工作來為程序間通訊架的橋樑。共享記憶體也是核心為程序間通訊駕的一座橋樑,只不過這座橋樑比其他橋樑更優,共享記憶體是核心為需要通訊

Linux高階程式設計9————程序通訊6訊號1

訊號是什麼? 訊號實質是一種軟中斷,用於通知程序發生了某些事件,實際上訊號也可以算作程序間通訊的一種方式,因為我們可在程序通過另一個程序傳送訊號,來告訴另一個程序發生什麼事。 這樣來講我們聽起來可能還會比較暈。 深入理解訊號: 在我們生活中其實就有訊號的

34-程序通訊——FIFO命名管道

1. 何為命名管道   在前面的學習中我們知道管道(pipe)只能用於“有血緣關係”的程序間。    它們之間最大的區別就是FIFO提供一個路徑名與之關聯,在檔案系統中有一個索引塊,以檔案路徑的形式存在(在磁碟中沒有資料塊,所有資料都存放在核心),而這個檔案路

Linux高階程式設計5————程序通訊1無名管道

程序通訊簡介: IPC(程序間通訊),前面我們學習了程序控制,瞭解程序間隔離的,各自有獨立的虛擬記憶體空間無法直接訪問對方的地址空間、程序排程和均衡則讓程序互不干擾地使用處理器資源。但有時需要多個程序相

Nginx原始碼分析與實踐---程序通訊機制套接字

在上一篇中,我們看到了nginx共享記憶體方式的程序間通訊。這次我們看下nginx使用套接字的程序間通訊方式。 同樣的幾個問題: 1.什麼時候需要使用套接字方式的程序間通訊機制呢? 舉個栗子:我們知道nginx有master程序和worker程序,那麼master程序是如何向w

Nginx原始碼分析與實踐---程序通訊機制共享記憶體

Nginx有一個master程序和多個worker程序,那麼master程序與worker程序間或worker程序之間是如何通訊的呢,又什麼時候需要程序間通訊呢? 我們知道linux下的程序間通訊方式主要有:管道、FIFO、套接字、訊息佇列、共享記憶體、訊號。那麼nginx的程序間通訊方式採