訊息佇列是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物件使用的控制方法和檔案系統非常類似。使用物件的引用標誌符作為資...