linux訊息佇列

2021-07-10 12:05:12 字數 3365 閱讀 3641

訊息佇列是linux中程序間通訊的方法之一。訊息佇列是乙個先進先出的佇列,對於同乙個型別的佇列,訊息是遵循先進先出的原則的。

訊息佇列的實現很簡單,只有四個函式就解決了,下面介紹下如何實現訊息佇列。

1 訊息佇列的建立

函式原型如下:

int msgget (key_t __key, int __msg***);

第乙個引數是乙個key,實際上就是乙個長整型,通過這個key唯一標識乙個訊息佇列。這個值可以是我們自己定義乙個唯一的整數。也可以通過 ftok來獲取乙個key。

第二個引數為識別符號,ipc_creat值,若沒有該佇列,則建立乙個並返回新識別符號;若已存在,則返回原識別符號。  

ipc_excl值,與ipc_creat一起使用。(用」|」連線),如果訊息佇列不存在則建立之,否則產生乙個錯誤並返回。

另外還要注意佇列的讀寫許可權,例如要支援讀寫需要這樣寫ipc_creat|0666.

該函式成功返回訊息佇列的id,失敗返回-1。

該函式返回的id唯一標識乙個訊息佇列。msgsnd 、msgrcv、msgctl都通過這個id來操作訊息佇列。

ftok的函式原型為

key_t ftok( const char * fname, int id );

fname 指定的已經存在的檔名或者目錄名(必須確保已經存在的檔名或者目錄。且不會被刪除)。該檔案或者目錄不存在將返回-1。

id 可以是自己指定的乙個整數。

該函式成功返回產生的key_t的值,失敗但會-1;

該函式,是將檔案的索引節點號取出,前面加上子序號得到key_t的返回值。

如果檔案被刪除再重新建立,那麼索引節點號就變了。用ftok建立的key就改變了,那麼就會造成程序不能訪問同乙個佇列了。所以要確保該檔案不會被刪除。

下面是示例**

int msgid; 

key_t key =  ftok(".", 20 );

msgid=msgget(key ,ipc_creat|0666);  

if(msgid<0)

2 傳送訊息:

函式原型如下:

int msgsnd (int __msqid, __const void *__msgp, size_t __msgsz, int __msg***);

__msqid 通過msgget 返回的訊息id

struct msgbuf ;

對於訊息的結構,我們可以不用上面的結構自己定義乙個結構。但是第乙個引數必須是訊息的型別,必須要和參考的結構一樣,為乙個long型。而且值必須大於等於1 。

mtype後面的成員我們可以任意指定。例如

struct mymsg ;

struct mymsg ;

__msgsz: 傳送訊息的尺寸,也就是__msgp 指向的資料的尺寸。

__msg***:為ipc_nowait表示不阻塞,也就是傳送的時候如果訊息佇列已滿,將直接返回-1。為0,如果訊息佇列滿將一直阻塞,直到函式可以向佇列寫資料為止。

該函式成功返回0 失敗返回-1。

3 接收訊息

函式原型如下:

int msgrcv (int __msqid, void *__msgp, size_t __msgsz, long int __msgtyp, int __msg***);

__msqid :通過msgget 返回的訊息id

__msgp  :指向接收訊息緩衝區的指標。

__msgsz:訊息緩衝區的尺寸,也就是__msgp 指向的緩衝區的大小。

__msgtyp :當__msgtyp 為0 時返回整個訊息佇列中的第乙個訊息。

當__msgtyp 大於0時返回訊息佇列中第乙個訊息型別等於__msgtyp 的訊息。訊息型別就是前面介紹的訊息參考結構中的mtype 。

當__msgtyp 小於0時,返回訊息佇列中第乙個訊息型別小於或者等於__msgtyp的絕對值 的第乙個訊息。

__msg***:為ipc_nowait表示不阻塞,也就是如果訊息隊列為空,將直接返回-1並且將錯誤碼設定為enomsg。為0,如果訊息隊列為空,將一直阻塞直到訊息佇列有資料為止。

該函式成功返回實際讀取的資料長度。 失敗返回-1。

注意這個函式呼叫一次只會返回一條訊息資料,即使指定__msgsz可以儲存多條訊息。

4 訊息佇列的其他操作:

函式原型如下:

int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf);

__msqid 通過msgget 返回的訊息id。

ipc_set  設定訊息佇列的資料結構msqid_ds中的ipc_perm元素的值。這個值取自__buf引數。

ipc_rmid 從系統核心中移走訊息佇列。不論訊息佇列中是否還有訊息,都將溢位訊息佇列。

該函式返回0 ,執行成功。

返回- 1,執行失敗:返回失敗是錯誤碼如下:

errno = eacces (沒有讀的許可權同時cmd 是ipc_stat )

efault (buf 指向的位址無效)

eidrm (在讀取中佇列被刪除)

einval (msgqid無效, 或者msgsz 小於0 )

eperm (ipc_set或者ipc_rmid 命令被使用,但呼叫程式沒有寫的許可權)

注意:因為訊息佇列是多程序共享的,所以程序結束後系統並不會主動釋放訊息佇列,所以我們在確保訊息佇列不用的時候要呼叫msgctl 釋放訊息佇列,以減少不必要的資源占用。

下面我們看看示例**:

typedef struct

my_msg;

int main(int argc, char** argv)

issend = argv[1][0]-0x30;//第乙個引數為0表示程序接收訊息,非0為表示程序傳送訊息

index = argv[2][0]-0x30;//第二個引數表示要接收的訊息的型別

if(issend==0)

}key_t key =  ftok(".", 2 );

printf("key_t = %d\n",key);

msgid=msgget(key ,ipc_creat|0666);  

if(msgid<0)

if(issend==1)

}else

else}}

return 0; 

}例如我們編譯出來的可執行檔案msgtest

我們分別在終端0執行  msgtest 1 0

在終端1執行  msgtest 0 1 

在終端2執行  msgtest 0 2 

在終端3執行  msgtest 0 3  

我們可以看到在終端0列印 send msg n的時候  (n為1-3)

對應的終端n   就會列印 process n get msg =[msg= n]  type=n    (n為1-3)

linux訊息佇列 Linux訊息佇列

訊息佇列,unix的通訊機制之一,可以理解為是乙個存放訊息 資料 容器。將訊息寫入訊息佇列,然後再從訊息佇列中取訊息,一般來說是先進先出的順序。可以解決兩個程序的讀寫速度不同 處理資料速度不同 系統耦合等問題,而且訊息佇列裡的訊息哪怕程序崩潰了也不會消失。最簡單的訊息記憶體的使用流程 ftok函式生...

linux訊息佇列

訊息佇列是核心位址空間中的內部鍊錶,每個訊息佇列都在系統範圍內對應唯一的鍵值,所以,要獲得乙個訊息佇列的描述字,只需提供該訊息佇列的鍵值即可。1 訊息緩衝區結構 存放訊息資料的模板,可在基本定義的基礎上自己定義 在include linux msg.h中宣告,描述如下 struct 可以定義自己的例...

linux 訊息佇列

一 訊息佇列的基本概念 訊息佇列 也叫做報文佇列 是unix系統v版本中3種程序間通訊機制之一。另外兩種是訊號燈和共享記憶體。這些ipc機制使用共同的授權方法。只有通過系統呼叫將標誌符傳遞給核心之後,程序才能訪問這些資源。這種系統ipc物件使用的控制方法和檔案系統非常類似。使用物件的引用標誌符作為資...