Linux程序間通訊 訊息佇列

2021-08-02 06:13:17 字數 3513 閱讀 7836

首先上篇文章我們說到了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裡面一樣的...