1. 程式人生 > >程序通訊——訊息對列

程序通訊——訊息對列

Linux下程序間通訊方式:

1. 管道( pipe ):管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的程序間使用。程序的親緣關係通常是指父子程序關係

2. 有名管道 (named pipe) : 有名管道也是半雙工的通訊方式,但是它允許無親緣關係程序間的通訊。

3. 訊號量( semophore ) : 訊號量是一個計數器,可以用來控制多個程序對共享資源的訪問。它常作為一種鎖機制,防止某程序正在訪問共享資源時,其他程序也訪問該資源。因此,主要作為程序間以及同一程序內不同執行緒之間的同步手段。

4. 訊息佇列( message queue ) : 訊息佇列是由訊息的連結串列,存放在核心中並由訊息佇列識別符號標識。訊息佇列克服了訊號傳遞資訊少、管道只能承載無格式位元組流以及緩衝區大小受限等缺點。

5. 訊號 ( sinal ) : 訊號是一種比較複雜的通訊方式,用於通知接收程序某個事件已經發生。

6. 共享記憶體( shared memory ) :共享記憶體就是對映一段能被其他程序所訪問的記憶體,這段共享記憶體由一個程序建立,但多個程序都可以訪問。共享記憶體是最快的 IPC 方式,它是針對其他程序間通訊方式執行效率低而專門設計的。它往往與其他通訊機制,如訊號兩,配合使用,來實現程序間的同步和通訊。

7. 套接字( socket ) : 套解口也是一種程序間通訊機制,與其他通訊機制不同的是,它可用於不同及其間的程序通訊。 下面我們來了解一下訊息對列

一、什麼是訊息佇列

訊息佇列提供了一種從一個程序向另一個程序傳送一個數據塊的方法。  每個資料塊都被認為含有一個型別,接收程序可以獨立地接收含有不同型別的資料結構。我們可以通過傳送訊息來避免命名管道的同步和阻塞問題。但是訊息佇列與命名管道一樣,每個資料塊都有一個最大長度的限制。

Linux用巨集MSGMAX和MSGMNB來限制一條訊息的最大長度和一個佇列的最大長度。

二、在Linux中使用訊息佇列 Linux提供了一系列訊息佇列的函式介面來讓我們方便地使用它來實現程序間的通訊。它的用法與其他兩個System V PIC機制,即訊號量和共享記憶體相似。

1、msgget函式 該函式用來建立和訪問一個訊息佇列。它的原型為:

int msgget(key_t key, int msgflg); 引數描述: key:是一個埠號,可以由ftok()生成 msgflg:  IPC_CREAT:如果IPC不存在,則建立,存在就開啟                 IPC_EXECL:單獨使用無太大意義,與IPC_CREAT一塊使用代表,IPC不存在建立,存在出錯,返回 key_t ftok(const char *pathname, int proj_id); 生成唯一一個key供使用者使用,返回一個訊息佇列識別符號。 返回值: 成功返回訊息佇列的id,失敗返回-1。

與其他的IPC機制一樣,程式必須提供一個鍵來命名某個特定的訊息佇列。msgflg是一個許可權標誌,表示訊息佇列的訪問許可權,它與檔案的訪問許可權一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的訊息佇列不存在時建立一個訊息佇列,如果key所命名的訊息佇列存在時,IPC_CREAT標誌會被忽略,而只返回一個識別符號。

它返回一個以key命名的訊息佇列的識別符號(非零整數),失敗時返回-1.

2、msgsnd函式 該函式用來把訊息新增到訊息佇列中。它的原型為: int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg); msgid是由msgget函式返回的訊息佇列識別符號。

msg_ptr是一個指向準備傳送訊息的指標,但是訊息的資料結構卻有一定的要求,指標msg_ptr所指向的訊息結構一定要是以一個長整型成員變數開始的結構體,接收函式將用這個成員來確定訊息的型別。所以訊息結構要定義成這樣:

struct my_message{    long int message_type;    /* The data you wish to transfer*/}; msg_sz是msg_ptr指向的訊息的長度,注意是訊息的長度,而不是整個結構體的長度,也就是說msg_sz是不包括長整型訊息型別成員變數的長度。

msgflg用於控制當前訊息佇列滿或佇列訊息到達系統範圍的限制時將要發生的事情。

如果呼叫成功,訊息資料的一分副本將被放到訊息佇列中,並返回0,失敗時返回-1.

3、msgrcv函式 該函式用來從一個訊息佇列獲取訊息,它的原型為 int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg); msgid, msg_ptr, msg_st的作用也函式msgsnd函式的一樣。

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 引數描述: msgid:訊息佇列的識別符號 msgp:指向一個緩衝區的指標,用來暫時存放儲存傳送和接受的訊息,是一個使用者可以定義的通用結構。 struct msgstru{     long mtype; //大於0     char mtext;//使用者指定大小 }; msgz:訊息的大小 msgtyp:從訊息佇列中讀取的訊息形態 msgflg:用來指明核心程式在佇列沒有資料的情況下所應採取的行動。如果msgflg和常 數IPC_NOWAIT合用,則在msgsnd()執行時若是訊息佇列已滿,則msgsnd()將不會阻塞,而 會立即返回-1,如果執⾏行的是msgrcv(),則在訊息佇列呈空時,不做等待馬上返回-1,並設定 錯誤碼為ENOMSG。當msgflg為0時,msgsnd()及msgrcv()在佇列呈滿或呈空的情形時,採取 阻塞等待的處理模式。 返回值: 成功返回實際讀取到的位元組數,失敗返回-1。

msgtype可以實現一種簡單的接收優先順序。如果msgtype為0,就獲取佇列中的第一個訊息。如果它的值大於零,將獲取具有相同訊息型別的第一個資訊。如果它小於零,就獲取型別等於或小於msgtype的絕對值的第一個訊息。

msgflg用於控制當佇列中沒有相應型別的訊息可以接收時將發生的事情。

呼叫成功時,該函式返回放到接收快取區中的位元組數,訊息被複制到由msg_ptr指向的使用者分配的快取區中,然後刪除訊息佇列中的對應訊息。失敗時返回-1.

4、msgctl函式 該函式用來控制訊息佇列,它與共享記憶體的shmctl函式相似,它的原型為: int msgctl(int msgid, int command, struct msgid_ds *buf); command是將要採取的動作,它可以取3個值,     IPC_STAT:把msgid_ds結構中的資料設定為訊息佇列的當前關聯值,即用訊息佇列的當前關聯值覆蓋msgid_ds的值。     IPC_SET:如果程序有足夠的許可權,就把訊息列隊的當前關聯值設定為msgid_ds結構中給出的值     IPC_RMID:刪除訊息佇列

buf是指向msgid_ds結構的指標,它指向訊息佇列模式和訪問許可權的結構。msgid_ds結構至少包括以下成員:

struct msgid_ds{    uid_t shm_perm.uid;    uid_t shm_perm.gid;    mode_t shm_perm.mode;}; 成功時返回0,失敗時返回-1.

參考:https://blog.csdn.net/ljianhui/article/details/10287879 參考:https://blog.csdn.net/sty23122555/article/details/51132158

參考:    https://blog.csdn.net/D_leo/article/details/72848774