程序間通訊之訊息佇列

2021-08-04 07:24:54 字數 4280 閱讀 8331

訊息佇列:

訊息佇列本質上是提供了一種從乙個程序向另乙個程序傳送資料快的方法。每個資料快都被認為是有乙個型別,接受者程序接收的資料塊可以有不同的型別值。

訊息佇列和管道的區別:

(1)、訊息佇列是基於訊息的,而管道是基於位元組流的,且訊息佇列的讀取不一定是先進先出的。

(2)、訊息佇列的生命週期是隨核心的(不隨程序的結束而結束),而管道的生命週期是隨程序的。

(3)、訊息佇列與命名管道有一樣的不足,就是每個訊息的最大長度是有上限的(msgmax),每個訊息佇列的總的位元組數是有上限的(msgmnb),系統上的訊息佇列的總數也有乙個上限(msgmni)。

ipc物件的資料結構:

核心為每個ipc物件維護了乙個資料結構(/usr/include/linux/ipc.h)

struct ipc_perm

;

訊息佇列,共享記憶體和訊號量都有這樣乙個共同的資料結構。

訊息佇列的結構(/usr/include/linux/msg.h)

struct msqid_ds ;
可以看到第乙個條目就是ipc結構體,即是公有的,後面的都是訊息佇列私有的成員。訊息佇列是用鍊錶實現的。

構建訊息佇列的介面:

1、建立新訊息佇列或取得已存在訊息佇列

int msgget(key_t key, int msg***);
引數:

key:可以認為是乙個埠號,也可以由函式ftok生成

msg***:

ipc_creat:如果ipc不存在,則建立乙個ipc資源,否則開啟操作。

ipc_excl:只有在共享記憶體不存在的時候,新的共享記憶體才建立,否則就產生錯位。如何單獨使用ipc_creat,msgget()函式要麼返回乙個已經存在的共享記憶體的操作符,要麼返回乙個新建的記憶體的識別符號。

如果ipc_creat和ipc_excl標誌一起使用,msgget()將返回乙個新建的ipc識別符號;如果該ipc資源已存在,或者返回-1。

ipc_exel標誌本身並沒有太大的意義,但是和ipc_creat標誌一起使用可以用來保證所得的物件是新建的,而不是開啟已有的物件。

2、向佇列讀/寫訊息

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msg***);

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msg***);

引數:

msgid:訊息佇列的標識碼

msgp:指向訊息緩衝區的指標,此位置用來暫時儲存傳送和接收的訊息,是乙個使用者可以定義的通用結構,形態如下:

long msgstru

;

msgsz:訊息的大小。

msgtyp:從訊息佇列內讀取的訊息形態。如果值為零,則表示訊息佇列中的所有訊息都會被讀取。

msg***:用來指明核心程式在佇列沒有資料的情況下所應採取的行動。如果msg***和常數ipc_nowait合用,則在

msgsnd()執行時若是訊息佇列已滿,則msgsnd()將不會阻塞,而會立即返回-1,如果執行的是msgrcv(),則在訊息隊

列呈空時,不做等待馬上返回-1,並設定錯誤碼為enomsg。當msg***為0時,msgsnd()及msgrcv()在佇列呈滿或呈

空的情形時,採取阻塞等待的處理模式。

3、設定訊息佇列屬性

int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
引數:

msgctl 系統呼叫對 msgqid 標識的訊息佇列執行 cmd 操作,系統定義了 3 種 cmd 操作: ipc_stat , ipc_set , ipc_rmid

ipc_stat : 該命令用來獲取訊息佇列對應的 msqid_ds 資料結構,並將其儲存到 buf 指定的位址空間。

ipc_set : 該命令用來設定訊息佇列的屬性,要設定的屬性儲存在buf中。 

ipc_rmid : 從核心中刪除 msqid 標識的訊息佇列。

key_t鍵

system v ipc使用key_t值作為它們的名字,在 readhat linux(後續驗證預設都在該平台下)下key_t被定義為int型別。

ftok函式

key_t ftok(const char *pathname, int proj_id);
引數 [pathname]:通常是跟本應用用關的目錄。

引數 [proj_id]:指的是本應用所用到的ipc的乙個序列號,成功返回ipc鍵,失敗返回-1。

注:兩程序如在pathname和proj_id上達成一致(或約定好),雙方就都能夠通過呼叫ftok函式得到同乙個ipc鍵。

pathname的實現是組合了三個鍵,分別是:

(1)、pathname所在檔案系統的資訊(stat結構的st_dev成員)。

(2)、pathname在本檔案系統內的索引節點號(stat結構的st_ino成員)。

(3)、id的低序8位(不能為0)。

ftok呼叫返回的整數ipc鍵由 proj_id的低序8位,st_dev成員的低序8位,st_info的低序16位組合而成。

不能保證兩個不同的路徑名與同乙個proj_id的組合產生不同的鍵,因為上面所列的三個條目(檔案系統識別符號、索引節點、proj_id)中的資訊位數可能大於乙個整數的資訊位數。

模擬實現**如下

#ifndef _comm_h

#define _comm_h

#include #include #include #include #include #define pathname "."

#define proj_id 0x6666

#define server_type 1

#define client_type 2

struct msgbuf

;int createmsgqueue();

int getmsgqueue();

int destroymstqueue(int msgid);

int senmsg(int msgid, int who, char* msg);

int recvmsg(int msgid, int recvtype, char out);

#endif

#include "comm.h"

static int commmsgqueue(int flags)

int msgid = msgget(_key, flags);

if(msgid < 0)

return msgid;

}int createmsgqueue()

int getmsgqueue()

int destroymsgqueue(int msgid)

return 0;

}int sendmsg(int msgid, int who, char* msg)

return 0;

}int recvmsg(int msgid, int recvtype, char out)

strcpy(out, buf.mtext);

return 0;

}

#include "comm.h"

int main()

recvmsg(msgid, server_type, buf);

printf("server# %s\n", buf);

}return 0;

}

#include "comm.h"

int main()

}destroymsgqueue(msgid);

return 0;

}

在linux下檢視訊息佇列ipcs -q, 而刪除訊息隊列為ipcrm -q msgid

執行結果和實驗**

程序間通訊之訊息佇列

include include define max msg buf len 512 int ikey 6004 struct ipcmsgbuf int main void 寫訊息佇列 memset msgdata,0,sizeof struct ipcmsgbuf msgdata.mtype 1...

程序間通訊之訊息佇列

訊息佇列其實就是提供了一種從乙個程序向另乙個程序傳送乙個資料塊的方法。我們可以通過傳送訊息來避免命名管道的同步和阻塞問題。此外,訊息佇列和管道不同的是,訊息佇列是基於訊息的,而管道是基於位元組流的,且訊息佇列不一定是先入先出。訊息佇列與命名管道有一樣的不足,就是每個訊息的最大長度是有上限的 msgm...

程序間通訊之訊息佇列

一訊息佇列 1,訊息佇列就是乙個訊息的鍊錶,把訊息看做乙個記錄,具有特定格式。程序可以向其中按照一定的規則新增新訊息 另一些程序則可以從訊息佇列中讀走訊息。2,分類 posi訊息佇列,系統v訊息佇列 大量使用 3,鍵值 訊息佇列的核心持續性要求每個訊息佇列都在系統範圍內對應唯一的鍵值,所以,要獲得乙...