首先上篇文章我們說到了linux下進行程序間通訊的一種方法或機制匿名管道和命名管道,那麼這裡要說的是另外一種與之不同的通訊方法,即訊息佇列,兩者之間有相同也有不同的地方,具體的下面就一一介紹。
一、什麼是訊息佇列?
首先它也是一種進行程序間通訊的方式,通過乙個程序向另外乙個程序傳送資料塊的方式,每個資料塊都被認為是有乙個型別的,而接受者程序接收的資料塊可以有不同的型別。
二、訊息佇列結構體
cat /usr/include/linux/msg.h
通過這個命令就可以查詢到訊息佇列的資料結構,如下圖:
該結構體第一條是乙個ipc結構體,是所有ipc機制(訊息佇列,訊號量,共享記憶體)所共有的,可以看出訊息佇列的底層是通過單鏈表來實現的。
三、訊息佇列相關的函式
1、建立新的訊息佇列或獲取已存在的訊息佇列
int
msgget(key_t key,int msg***);
這裡的key是乙個鍵,用來標識某個特定的訊息佇列。
而msg***呢,包含兩個識別符號ipc_creat和ipc_excl ,ipc_creat的意思為,如果ipc不存在,則建立乙個ipc資源。而ipc_excl則是只有在共享記憶體不存在的時候,新的共享記憶體才建立,否則產生錯誤。一般情況下兩者必須同時存在,才能保證所得物件是新建的。
2、訊息的讀/寫
讀取訊息
ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msg***);
放入訊息
int msgsnd(int msqid,const
void *msgp,size_t msgsz,int msg***);
msqid就是訊息佇列的標識碼,msgp是指向訊息緩衝區的指標,這個位置是用來暫時儲存傳送和接收的訊息,是乙個使用者可自定義的結構:
struct msgstru
msgsz是訊息的大小,msgtyp是讀取訊息的形態,如果為0.則會讀取佇列裡所有的訊息。
msg***則是表明在佇列裡沒有資料的情況下程式所採取的行動,如果msg***和常數ipc_nowait合用,則在執行msgsnd()執行時若訊息佇列已滿,則msgsnd()將不會阻塞,而會立即返回-1,如果執行的是msgrcv(),則在訊息隊列為空時,直接返回-1,當msg***為0時,則當佇列呈滿或呈空時,採取阻塞等待的處理方式。
3、訊息佇列的屬性
int
msgctl(int msgqid,int cmd,struct msqid_ds *buf);
cmd是所要執行的操作,一共定義了三種:
ipc_stat:獲取訊息佇列中對應的msqid_ds結構,將其儲存到buf中。
ipc_set:所要設定的屬性,然後儲存在buf中。
ipc_rmid:從核心中刪除msqid標識的訊息佇列。
4、ftok函式
key_t ftok(const
char *pathname,int proj_id);
通過ftok函式可以將乙個已存在路徑和乙個整數標識轉換為乙個key_t的值,就是用來標識特定訊息的。
四、**測試,熟悉介面。
接收訊息端:msg_receive.c
#include
#include
#include
#include
#include
#include
#define filepath "."
#define id 0
struct msg_info
;int main()
msgid = msgget(_key,0666 | ipc_creat);//獲取訊號佇列id
if(msgid == -1)
while(1)
printf("you wrote:%s\n",data.mtext);
if(strncmp(data.mtext,"end",3) == 0)
break;
}if(msgctl(msgid,ipc_rmid,0) == -1)
return
0;}
傳送訊息端:msg_send.c
#include
#include
#include
#include
#include
#include
#define filepath "."將路徑定義為當前目錄
#define id 0
#define max_mtext 1024
struct msg_info
;int main()
msgid = msgget(_key,0666 | ipc_creat);
if(msgid == -1)
while(1)
if(strncmp(buffer,"end",3) == 0)
break;
sleep(1);
}return
0;}
程式的結果如下圖:
這樣就實現了兩個程序間的通訊。
五、和管道之間的異同
相同:每個訊息它也是有最大長度的限制的,所以兩者在位元組限制這塊是相同的,並且都可以實現兩個不相干程序間的資訊傳遞,在管道中我們也通過小例子來測出了它的大小,下面就看下系統中各自的分配的大小:
可以發現這裡的65536和上節管道裡測出的相同(沒有問題吧!^_^)
不同:訊息佇列是基於訊息的,所以它的讀取不一定是先入先出,是帶有選擇性的。而管道是基於位元組流的,這樣訊息佇列就有效避免了命名管道的同步和阻塞問題。
最後給出兩個程式的makefile:
.phony:all
all:msg_send msg_receive
msg_send:msg_send.c
gcc -o $@ $^
msg_receive:msg_receive.c
gcc -o $@ $^
.phony:clean
clean:
rm -f msg_send msg_receive
Linux程序間通訊 訊息佇列
linux和類linux系統下程序間通訊 inter process communication,ipc 有很多種方式,包括套接字 socket 共享記憶體 shared memory 管道 pipe 訊息佇列 message queue 等,各自有各自的一些應用場景和用途,這次就來聊一聊訊息佇列這...
linux程序間通訊 訊息佇列
訊息佇列由id 唯一標識 訊息佇列就是乙個訊息的列表,使用者可在佇列中新增,讀取訊息等 可按照型別來收發訊息 int msgget key t key,int flag int msgsnd int msqid,const void msgp,size t size,int flag msqid 訊...
linux程序間通訊 訊息佇列
訊息佇列屬於ipc 兩個程序間要通過訊息佇列進行通訊,比如a通過訊息佇列給b傳送乙個訊息。首先a要建立乙個訊息佇列,然後a往該訊息佇列裡面傳送訊息 由乙個有特殊形式的結構體構成,包括資料型別和資料內容 當不需要使用這個訊息佇列的時候刪除訊息佇列。b要做的事情是開啟訊息佇列,開啟方式是用和a裡面一樣的...