linux訊息佇列程序通訊

2021-06-03 12:39:55 字數 3949 閱讀 7564

訊息佇列 

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

訊息佇列就是乙個訊息的鍊錶。就是把訊息看作乙個記錄,並且這個記錄具有特定的格式以及特定的優先順序。對訊息佇列有寫許可權的程序可以按照一定的規則新增新訊息;對訊息佇列有讀許可權的程序則可以從訊息佇列中讀出訊息。

linux採用訊息佇列的方式來實現訊息傳遞。這種訊息的傳送方式是:傳送方不必等待接收方檢查它所收到的訊息就可以繼續工作下去,而接收方如果沒有收到訊息也不需等待。這種通訊機制相對簡單,但是應用程式使用起來就需要使用相對複雜的方式來應付了。新的訊息總是放在佇列的末尾,接收的時候並不總是從頭來接收,可以從中間來接收。

訊息佇列是隨核心持續的並和程序相關,只有在核心重起或者顯示刪除乙個訊息佇列時,該訊息佇列才會真正被刪除。因此系統中記錄訊息佇列的資料結構 (struct ipc_ids msg_ids)位於核心中,系統中的所有訊息佇列都可以在結構msg_ids中中找到訪問入口。

ipc識別符號:每乙個i p c目標都有乙個唯一的i p c識別符號。這裡所指的i p c目標是指乙個單獨的訊息佇列、乙個訊號量集或者乙個共享的記憶體段。系統核心使用此識別符號在系統核心中指明 i p c目標。

ipc 關鍵字:想要獲得唯一的識別符號,則必須使用乙個 i p c關鍵字。客戶端程序和伺服器端程序必須雙方都同意此關鍵字。這是建立乙個客戶機/伺服器框架的第一步。在system v ipc機制中,建立兩端聯絡的路由方法是和i p c關鍵字直接相關的。通過在應用程式中設定關鍵字值,每一次使用的關鍵字都可以是相同的。一般情況下,可以使用f t o k ( )函式為客戶端和伺服器端產生關鍵字值。

命令ipcs用於讀取system v ipc目標的狀態。

ipcs -q: 只顯示訊息佇列。

ipcs -s: 只顯示訊號量。

ipcs -m: 只顯示共享記憶體。

ipcs –help: 其他的引數。 

三、訊息佇列的主要呼叫

核心中實現訊息傳遞機制的**基本上都在檔案ipc/msg.c中,訊息佇列的主要呼叫有下面4個

(1)msgget:呼叫者提供乙個訊息佇列的鍵標 (用於表示個訊息佇列的唯一名字),當這個訊息佇列存在的時候, 這個訊息呼叫負責返回這個佇列的標識號;如果這個佇列不存在,就建立乙個訊息佇列,然後返回這個訊息佇列的標識號 ,主要由sys_msgget執行。

(2)msgsnd:向乙個訊息佇列傳送乙個訊息,主要由sys_msgsnd執行。

(3)msgrcv:從乙個訊息佇列中收到乙個訊息,主要由sys_msgrcv執行。

(4)msgctl:在訊息佇列上執行指定的操作。根據引數的不同和許可權的不同,可以執行檢索、刪除等的操作,主要由sys_msgctl執行。

#include 

#include 

#include 

int     msgget( key_t msgkey , int flag );

取得乙個訊息佇列的id,如不存在則建立。

返回值:        成功時:訊息佇列的id

失敗時:-1

int     msgsnd( int msqid , struct msgbuf *msgp , size_t msgsiz , int msgflag );

向訊息佇列送訊息

返回值:        成功時:0

失敗時:-1

msqid是訊息佇列的id,size_t msgsiz是結構體成員mdata的大小,msgflag與上一章所講的共享記憶體的flag起一樣的作用,不過,當這個引數為ipc_nowait的時候,如果訊息佇列已滿,則返回錯誤值。如果不為ipc_nowait,在訊息佇列已滿 的情況下,會一直等到訊息佇列有空地方的時候再傳送。

注意這裡的這個 struct msgbuf *msgp 。要求的格式如下:

struct  msgbuf

;long mtype在這裡我們用來儲存本程序的pid。mdata則是儲存要傳送的資料。由於mdata的大小不一定(根據實際需要定義),所以這個結構體並沒有事先定義好。但是我們定義這個結構體的時候一定要遵循這個規定。你可以改的,只有mdata的大小,和結構體的名稱。盡量不要修改結構體成員的名稱和型別。實際上,根據mtype,我們還可以有所選擇地接受訊息。這在下面將會談到。

int     msgrcv( int msqid , struct msgbuf *msgp , size_t msgsiz , long msgtyp , int msgflag );

從訊息佇列取得乙個訊息

返回值:        成功時:0

失敗時:-1

msqid , *msgp , msgsiz不用說了。long msgtyp是結構體msgbuf的mtype成員。msgflag與上述一樣。只不過為ipc_nowait的時候,如果訊息佇列是空的,則等到有訊息可讀的時候再讀。當不為ipc_nowait的時候,如果訊息佇列是空的,則返回錯誤值(與字面上理解的有些相反)

下面這個鏈結幫助了我更好地理解了msgrcv  中的 long msgtyp這個引數和

struct  msgbuf

;裡的long mtype這個結構體成員。

同樣地,為了控制管理訊息佇列,一樣有乙個函式msgctl()如下:

#include 

#include 

#include 

int     msgctl( int msqid , int cmd , struct msqid_ds *buf );

返回值:        成功時:0

失敗時:-1

cmd所指定的值與共享記憶體部分相同。

最後自己寫了乙個利用訊息佇列實現程序通訊

基本思路:

我每次將a端傳送訊息時的訊息型別標記為奇數,將b端傳送的訊息型別為偶數。

a端讀取訊息型別為偶數的訊息(也就是說是從b端傳送過來的)

b端讀取訊息型別為奇數的訊息(也就是說是從a端傳送過來的)

#include #include #include #include int main()

; struct msgbuf msgdata , *p ;

p = &msgdata ;

msgkey = ftok( "." , 'a' ); /*計算識別符號*/

msqid = msgget( msgkey , ipc_creat | 0666 ) ;  /*取得訊息佇列的id*/

while(1)

msgrcv( msqid , p , sizeof(p->mdata) , count+1 , 0 ) ;   /*讀訊息*/

if (p->mtype % 2 == 1)

}return 0;

}

#include #include #include #include int main()

; struct msgbuf msgdata , *p ;

p = &msgdata ;

msgkey = ftok ( "." , 'a' );

msqid = msgget( msgkey , ipc_creat | 0666 ) ;

while(1)

msgrcv( msqid , p , sizeof(p->mdata) , count-1 , 0 ) ;

if (p->mtype % 2 == 0) }

return 0;

}

a.c和b.c 程式基本上是一樣的

這個程式還有一些不完善的地方:

1.每個埠不能連續輸入,必須等對方輸入以後才 會顯示結果。這裡我也不清楚怎麼回事。gdb的除錯還不太會,錯誤不太會找。希望高手指教,呵呵

2.沒有刪除訊息佇列,下次開啟時候還會殘留以前的訊息

Linux程序通訊 訊息佇列

1.訊息佇列 訊息佇列也稱為報文佇列,訊息佇列是隨核心持續的,只有在核心重起或顯示刪除乙個訊息佇列時,該訊息佇列才會真正刪除 系統中記錄訊息佇列的資料結構struct ipc ids msg ids位於核心中,系統中所有訊息佇列都可以在結構msg ids中找到訪問入口 訊息佇列其實就是乙個訊息的鍊錶...

linux 程序 訊息佇列通訊

1.概述 該demo主要實現linux下程序之間的訊息佇列通訊,相關介面介紹可以參考 2.場景 半雙工 父程序簡單地通過訊息佇列將資料傳送給子程序 3.測試 程序程式設計demo 訊息佇列 ipc相關的命令 ipcs ipcrm 釋放ipc 檢視程序屬性 ulimit a include inclu...

Linux程序通訊 訊息佇列

博文 程式設計步驟 步驟程序1 程序2使用函式 1獲取到key 獲取到key msgget 2使用key建立訊息佇列拿到訊息id 使用key獲取到訊息佇列的id msgget 3傳送訊息 接收訊息 msgsnd msgrev 4釋放訊息佇列 釋放訊息佇列 msgctl 例項程式 程序1 讀 int ...