1. 程式人生 > >Linux之訊息佇列機制

Linux之訊息佇列機制

一.訊息佇列先知
其實,訊息佇列與命名管道有很多相似之處,但少了在開啟和關閉管道方面的複雜性。但使用訊息佇列應為解決我們在,命名管道時遇到的一些問題,比如管道的阻塞問題。
訊息佇列提供了一種子啊兩個不想管的程序之間傳遞資料的相當簡單且有效的方法,與命名管道相比,訊息佇列的優勢在於,它獨立於傳送和接收程序而存在。
訊息佇列提供了一種從一個程序想另一個程序傳送一個數據塊的方法。每個資料塊都被認為含有一個型別,接收程序可以獨立地接收含有不同型別值的資料塊。但是,這些資料塊都有一個最大長度的先知,系統中所有佇列所包含的全部資料塊的長度也有一個上限。
二.訊息佇列有關的函式
訊息佇列函式都包含在一個頭檔案中:

#include<sys/msg.h>

建立和訪問一個訊息佇列的函式msgget()

int msgget(key_t key,int msgflg)
//第一個引數key,通過這個鍵值來命名某個特定的訊息佇列
//第二個引數msgflg,由9個許可權標誌組成
//由IPC_CREATE定義的一個特殊位必須和許可權標誌位或才能建立一個新的訊息佇列

把訊息新增到訊息佇列的函式msgsnd()

int msgsnd(int msqid,const void *msg_ptr,size_t msg_sz,int msgflg)
//第一個引數msqid,是由msgget函式返回的訊息佇列識別符號
//第二個引數msg_ptr,是一個指向準備傳送訊息的指標 //第三個引數msg_sz,是msg_ptr指向的訊息的長度 //第四個引數msgsnd,控制在當前訊息佇列滿或佇列訊息到達系統範圍的限制時將要發生的事情

從一個訊息佇列中獲取訊息的函式msgrcv()

int msgrcv(int msqid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg)
//第一個引數msqid,是由msgget函式返回的訊息佇列識別符號
//第二個引數msg_ptr,是一個指向準備接受訊息的指標
//第三個指標msg_sz,是msg_ptr指向的訊息的長度
//第四個引數msgtype,實現一種簡單形式的接收優先順序
//第五個引數msgflg,用於控制當前佇列中沒有響應型別的訊息可以接收時將發生的事情

訊息佇列的控制函式msgctl()

int msgctl(int msgid,int command,struct msgid_ds *buf)
//第一個引數msgid,是由mdsgget返回的訊息佇列識別符號
//第二個引數command,是將要採取的動作
//第三個引數是一個結構體

結構體內容如下:

struct msgid_ds{
    uid_t msg_perm.uid;
    uid_t msg_perm.gid;
    uid_t msg_perm.mode;
};

三.原始碼實現
main.c//向訊息佇列記憶體寫入

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/msg.h>

struct mess
{
    long type;
    char buff[128];
};

int main()
{
    int msgid = msgget((key_t)1357,IPC_CREAT|0666);
    assert(msgid != -1);

    struct mess dt;
    dt.type = 2;
    strcpy(dt.buff,"i am zkr");

    //int i = 1;
    //for(;i<65536;i++)
    //{
        msgsnd(msgid,(void*)&dt,128,0);//這裡的大小隻是資料的大小
        //printf("i = %d\n",i);
    //}
}

test.c//列印main.c裡邊的內容

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/msg.h>

struct mess
{
    long type;
    char buff[128];
};

int main()
{
    int msgid = msgget((key_t)1357,IPC_CREAT|0666);
    assert(msgid != -1);

    struct mess dt;
    dt.type = 2;
    strcpy(dt.buff,"i am zkr");

    msgrcv(msgid,(void*)&dt,128,0,0);
    printf("dt.buff = %s\n",dt.buff);

}

四.結果展示

這裡寫圖片描述
這裡補充個小知識:
我們可以利用命令ipcs -q檢視訊息佇列
如果在沒有建立訊息佇列之前,應該是這樣的:
這裡寫圖片描述
執行完程式再檢視應該是這樣的:
這裡寫圖片描述
其實到現在我們可以看出,訊息佇列的建立是在程式之外的,換而言之,就是說訊息佇列建立完成之後並不會因為程式結束被釋放空間。那麼,我們可以用ipcrm -q +msqid 命令來刪除訊息佇列,如下:
這裡寫圖片描述