1. 程式人生 > >程序間通訊----使用訊息佇列

程序間通訊----使用訊息佇列

面來說說如何用不用訊息佇列來進行程序間的通訊,訊息佇列與命名管道有很多相似之處。有關命名管道的更多內容可以參閱我的另一篇文章:Linux程序間通訊——使用命名管道 一、什麼是訊息佇列 訊息佇列提供了一種從一個程序向另一個程序傳送一個數據塊的方法。  每個資料塊都被認為含有一個型別,接收程序可以獨立地接收含有不同型別的資料結構。我們可以通過傳送訊息來避免命名管道的同步和阻塞問題。但是訊息佇列與命名管道一樣,每個資料塊都有一個最大長度的限制。 Linux用巨集MSGMAX和MSGMNB來限制一條訊息的最大長度和一個佇列的最大長度。 二、在Linux中使用訊息佇列 Linux提供了一系列訊息佇列的函式介面來讓我們方便地使用它來實現程序間的通訊。它的用法與其他兩個System V PIC機制,即訊號量和共享記憶體相似。 1、msgget函式
該函式用來建立和訪問一個訊息佇列。它的原型為:
int msgget(key_t, key, int msgflg);
與其他的IPC機制一樣,程式必須提供一個鍵來命名某個特定的訊息佇列。msgflg是一個許可權標誌,表示訊息佇列的訪問許可權,它與檔案的訪問許可權一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的訊息佇列不存在時建立一個訊息佇列,如果key所命名的訊息佇列存在時,IPC_CREAT標誌會被忽略,而只返回一個識別符號。 它返回一個以key命名的訊息佇列的識別符號(非零整數),失敗時返回-1. 2、msgsnd函式 該函式用來把訊息新增到訊息佇列中。它的原型為:
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
msgid是由msgget函式返回的訊息佇列識別符號。 msg_ptr是一個指向準備傳送訊息的指標,但是訊息的資料結構卻有一定的要求,指標msg_ptr所指向的訊息結構一定要是以一個長整型成員變數開始的結構體,接收函式將用這個成員來確定訊息的型別。所以訊息結構要定義成這樣:
struct my_message{
    long int message_type;
    /* The data you wish to transfer*/
};
msg_sz是msg_ptr指向的訊息的長度,注意是訊息的長度,而不是整個結構體的長度,也就是說msg_sz是不包括長整型訊息型別成員變數的長度。
msgflg用於控制當前訊息佇列滿或佇列訊息到達系統範圍的限制時將要發生的事情。 如果呼叫成功,訊息資料的一分副本將被放到訊息佇列中,並返回0,失敗時返回-1. 3、msgrcv函式 該函式用來從一個訊息佇列獲取訊息,它的原型為
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
msgid, msg_ptr, msg_st的作用也函式msgsnd函式的一樣。 msgtype可以實現一種簡單的接收優先順序。如果msgtype為0,就獲取佇列中的第一個訊息。如果它的值大於零,將獲取具有相同訊息型別的第一個資訊。如果它小於零,就獲取型別等於或小於msgtype的絕對值的第一個訊息。 msgflg用於控制當佇列中沒有相應型別的訊息可以接收時將發生的事情。 呼叫成功時,該函式返回放到接收快取區中的位元組數,訊息被複制到由msg_ptr指向的使用者分配的快取區中,然後刪除訊息佇列中的對應訊息。失敗時返回-1. 4、msgctl函式 該函式用來控制訊息佇列,它與共享記憶體的shmctl函式相似,它的原型為:
int msgctl(int msgid, int command, struct msgid_ds *buf);
command是將要採取的動作,它可以取3個值,     IPC_STAT:把msgid_ds結構中的資料設定為訊息佇列的當前關聯值,即用訊息佇列的當前關聯值覆蓋msgid_ds的值。     IPC_SET:如果程序有足夠的許可權,就把訊息列隊的當前關聯值設定為msgid_ds結構中給出的值
    IPC_RMID:刪除訊息佇列 buf是指向msgid_ds結構的指標,它指向訊息佇列模式和訪問許可權的結構。msgid_ds結構至少包括以下成員:
struct msgid_ds
{
    uid_t shm_perm.uid;
    uid_t shm_perm.gid;
    mode_t shm_perm.mode;
};
成功時返回0,失敗時返回-1. 三、使用訊息佇列進行程序間通訊 馬不停蹄,介紹完訊息佇列的定義和可使用的介面之後,我們來看看它是怎麼讓程序進行通訊的。由於可以讓不相關的程序進行行通訊,所以我們在這裡將會編寫兩個程式,msgreceive和msgsned來表示接收和傳送資訊。根據正常的情況,我們允許兩個程式都可以建立訊息,但只有接收者在接收完最後一個訊息之後,它才把它刪除。 接收資訊的程式原始檔為msgreceive.c的原始碼為:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>

struct msg_st
{
	long int msg_type;
	char text[BUFSIZ];
};

int main()
{
	int running = 1;
	int msgid = -1;
	struct msg_st data;
	long int msgtype = 0; //注意1

	//建立訊息佇列
	msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
	if(msgid == -1)
	{
		fprintf(stderr, "msgget failed with error: %d\n", errno);
		exit(EXIT_FAILURE);
	}
	//從佇列中獲取訊息,直到遇到end訊息為止
	while(running)
	{
		if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1)
		{
			fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
			exit(EXIT_FAILURE);
		}
		printf("You wrote: %s\n",data.text);
		//遇到end結束
		if(strncmp(data.text, "end", 3) == 0)
			running = 0;
	}
	//刪除訊息佇列
	if(msgctl(msgid, IPC_RMID, 0) == -1)
	{
		fprintf(stderr, "msgctl(IPC_RMID) failed\n");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}
傳送資訊的程式的原始檔msgsend.c的原始碼為:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>

#define MAX_TEXT 512
struct msg_st
{
	long int msg_type;
	char text[MAX_TEXT];
};

int main()
{
	int running = 1;
	struct msg_st data;
	char buffer[BUFSIZ];
	int msgid = -1;

	//建立訊息佇列
	msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
	if(msgid == -1)
	{
		fprintf(stderr, "msgget failed with error: %d\n", errno);
		exit(EXIT_FAILURE);
	}

	//向訊息佇列中寫訊息,直到寫入end
	while(running)
	{
		//輸入資料
		printf("Enter some text: ");
		fgets(buffer, BUFSIZ, stdin);
		data.msg_type = 1;    //注意2
		strcpy(data.text, buffer);
		//向佇列傳送資料
		if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
		{
			fprintf(stderr, "msgsnd failed\n");
			exit(EXIT_FAILURE);
		}
		//輸入end結束輸入
		if(strncmp(buffer, "end", 3) == 0)
			running = 0;
		sleep(1);
	}
	exit(EXIT_SUCCESS);
}
執行結果如下:
四、例子分析——訊息型別 這裡主要說明一下訊息型別是怎麼一回事,注意msgreceive.c檔案main函式中定義的變數msgtype(註釋為注意1),它作為msgrcv函式的接收資訊型別引數的值,其值為0,表示獲取佇列中第一個可用的訊息。再來看看msgsend.c檔案中while迴圈中的語句data.msg_type = 1(註釋為注意2),它用來設定傳送的資訊的資訊型別,即其傳送的資訊的型別為1。所以程式msgreceive能夠接收到程式msgsend傳送的資訊。 如果把注意1,即msgreceive.c檔案main函式中的語句由long int msgtype = 0;改變為long int msgtype = 2;會發生什麼情況,msgreceive將不能接收到程式msgsend傳送的資訊。因為在呼叫msgrcv函式時,如果msgtype(第四個引數)大於零,則將只獲取具有相同訊息型別的第一個訊息,修改後獲取的訊息型別為2,而msgsend傳送的訊息型別為1,所以不能被msgreceive程式接收。重新編譯msgreceive.c檔案並再次執行,其結果如下:
我們可以看到,msgreceive並沒有接收到資訊和輸出,而且當msgsend輸入end結束後,msgreceive也沒有結束,通過jobs命令我們可以看到它還在後臺執行著。 五、訊息佇列與命名管道的比較 訊息佇列跟命名管道有不少的相同之處,通過與命名管道一樣,訊息佇列進行通訊的程序可以是不相關的程序,同時它們都是通過傳送和接收的方式來傳遞資料的。在命名管道中,傳送資料用write,接收資料用read,則在訊息佇列中,傳送資料用msgsnd,接收資料用msgrcv。而且它們對每個資料都有一個最大長度的限制。 與命名管道相比,訊息佇列的優勢在於,1、訊息佇列也可以獨立於傳送和接收程序而存在,從而消除了在同步命名管道的開啟和關閉時可能產生的困難。2、同時通過傳送訊息還可以避免命名管道的同步和阻塞問題,不需要由程序自己來提供同步方法。3、接收程式可以通過訊息型別有選擇地接收資料,而不是像命名管道中那樣,只能預設地接收。

相關推薦

php程序通訊--訊息佇列

首先我們來看一下如何建立一個訊息佇列。 //建立訊息佇列 $msg_key = ftok( __FILE__, 'a' ); $msg_queue = msg_get_queue( $msg_key, 0666 );  在php中通過這兩句話就可以建立一個訊息佇列。 ftok 函式,是可以

Linux關於程序通訊訊息佇列

訊息佇列概念 訊息佇列提供了一個從一個程序向另外一個程序傳送一塊資料的方法 每個資料塊都被認為是有一個型別,接收者程序接收的資料塊可以有不同的型別值 訊息佇列也有管道一樣的不足,就是每個資料塊的最大長度是有上限的,系統上全體佇列的最大總長度也有一個上限 訊息佇列函式操作

python 多程序通訊 訊息佇列

import multiprocessing import time #使用佇列,將訊息寫進佇列,需要的程序到佇列取 #佇列由父程序建立,子程序共享佇列 def write(qe): print("啟動子程序 write") for chr in ['A','B','C','D

程序通訊——訊息佇列

每個程序各自具有不同的使用者地址空間,任何一個程序的全域性變數在另外一個程序中看不到;所以程序之間要交換資料必須通過核心,在核心中開闢一塊緩衝區,程序1把資料從使用者空間拷到核心緩衝區,程序2再從核心緩

一步一步學linux之程序通訊——訊息佇列

一、什麼是訊息佇列:訊息佇列提供了一種程序與程序間傳送資料塊的一種方法,每個資料塊含有一個型別,接收程序可以獨立地接收含有不同型別的資料結構,可以通過傳送訊息來避免同步和阻塞問題。訊息佇列有最大長度限制       在分散式計算環境下,訊息佇列是為了對異構網路環境下的分散式應

Linux程序通訊——訊息佇列應用例項

    訊息佇列是訊息的連結表,包括Posix訊息佇列system V訊息佇列。有足夠許可權的程序可以向佇列中新增訊息,被賦予讀許可權的程序則可以讀走佇列中的訊息。訊息佇列克服了訊號承載資訊量少,管道只能承載無格式位元組流以及緩衝區大小受限等缺點。下面是兩個測試模組接收模組m

System V程序通訊---訊息佇列

一、訊息佇列模型 訊息佇列是訊息的鏈式佇列,下圖即為訊息佇列模型… 1、訊息佇列的基本屬性 struct msqid_ds { struct msqid_ds { struct ipc_perm msg_perm;

PHP 程序通訊——訊息佇列(msg_queue)

PHP 程序間通訊——訊息佇列 本文不涉及PHP基礎庫安裝。詳細安裝說明,請參考官網,或期待後續部落格分享。 1、訊息佇列函式準備 <?php //生成一個訊息佇列的key $msg_key = ftok(__FILE__, 'a'); //產生一個訊息佇列

linux程序通訊--訊息佇列相關函式(ftok)詳解

ipc_perm中mode的含義 操作者 讀 寫 可讀可寫 使用者 0400 0200 0600 組 0040 0020 0060 其他 0004 0002 0006 5.  IPC物件的建立許可權     msgget、semget、sh

Linux 程序通訊——訊息佇列實現雙向通訊

函式: key_t ftok(const char *filename, int proj_id); 通過檔名和專案號獲得System V IPC鍵值(用於建立訊息佇列、共享記憶體所用) proj_id:專案號,不為0即可 返回:成功則返回鍵值,失敗則返回-1 函式: in

程序通訊佇列,管道,檔案,共享記憶體,訊號量,事件,互斥鎖,socket

2017/11/4 程序間通訊,程序池 程序間通訊(IPC,inter-process communication):生產程序生產食物,消費程序購買食物,消費程序一直監視生產狀況,只要一有食物就將其取出來,如果取到食物None,兩者關係結束,於是主程序也結束。 遠端過程呼叫

程序通訊——訊息傳遞(訊號量同步PV操作)

【申明:本文僅限於自我歸納總結和相互交流,有紕漏還望各位指出。 聯絡郵箱:[email protected]】 在多工作業系統環境下,多程序/多執行緒間同時執行,並且這些程序之間存在一定的關聯,多個程序/執行緒可能為了完成同一個任務相互協作,這就是程序之間的同步,

Linux:程序通訊(匿名管道命名管道)(共享記憶體,訊息佇列,訊號量)

目錄 程序間通訊的介紹 管道 匿名管道 原理: 程式碼實現 匿名管道特性 實現管道符 |  命名管道 命名管道特性 程式碼實現 管道讀寫規則 作業系統中ipc的相關命令 共享記憶體(重點) 生命週期: 程式碼實現 程式碼實現獲

Linux中程序通訊機制----訊息佇列

一、什麼是訊息 訊息(message)是一個格式化的可變長的資訊單元。訊息機制允許由一個程序給其它任意的程序傳送一個訊息。當一個程序收到多個訊息時,可將它們排成一個訊息佇列。 1、訊息機制的資料結構 (1)訊息首部 記錄一些與訊息有關的資訊,如訊息的型別、大小、

程序通訊的方式——訊號、管道、訊息佇列、共享記憶體

多程序: 首先,先來講一下fork之後,發生了什麼事情。 由fork建立的新程序被稱為子程序(child process)。該函式被呼叫一次,但返回兩次。兩次返回的區別是子程序的返回值是0,而父程序的返回值則是新程序(子程序)的程序 id。將子程序id返回給父程序的理由是

嵌入式Linux併發程式設計,程序通訊方式,System V IPC,訊息佇列,開啟/建立msgget(), 傳送訊息msgsnd(),格式,接收訊息msgrcv(),控制訊息佇列 msgctl()

文章目錄 1,訊息佇列 2,訊息佇列結構 3,訊息佇列使用步驟 3.1,開啟/建立訊息佇列 msgget() 3.1.1,開啟/建立訊息佇列---示例msgget() 3.2,向訊息佇列傳送訊息 msgs

Linux系統程式設計——程序通訊訊息佇列

概述 訊息佇列提供了一種在兩個不相關的程序之間傳遞資料的簡單高效的方法,其特點如下: 1)訊息佇列可以實現訊息的隨機查詢。訊息不一定要以先進先出的次序讀取,程式設計時可以按訊息的型別讀取。 2)訊息佇列允許一個或多個程序向它寫入或者讀取訊息。 3)與無名管道、命名管道一

(三)程序通訊方式-----訊息佇列

訊息佇列 訊息佇列,是訊息的連結表,存放在核心中。一個訊息佇列由一個識別符號(即佇列ID)來標識。使用者程序可以向訊息佇列新增訊息,也可以向訊息佇列讀取訊息。 同管道檔案相比,訊息佇列中的每個訊息指定特定的訊息型別,接收的時候可以不需要按照佇列次序讀取,可以根據自定義型別

【Linux】Linux程序通訊訊息佇列

1、訊息佇列概念引入    訊息佇列提供了一個從一個程序向另外一個程序傳送一塊資料的方法每個資料塊都被認為是有一個型別,接收者程序接收的資料塊可以有不同的型別值訊息佇列也有管道一樣的不足,就是每個訊息的最大長度是有上限的(MSG

Linux環境程序通訊(三) 訊息佇列(轉)

轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part3/, 作者:鄭彥興訊息佇列(也叫做報文佇列)能夠克服早期unix通訊機制的一些缺點。作為早期unix通訊機制之一的訊號能夠傳送的資訊量有限,後來雖然 POSIX 1003.1b在訊號的實時性方面作了