欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)

 更新時(shí)間:2022年08月30日 15:34:15   作者:咋么又餓了  
這篇文章主要介紹了C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收),消息隊(duì)列是一種先進(jìn)先出的隊(duì)列型數(shù)據(jù)結(jié)構(gòu),實(shí)際上是系統(tǒng)內(nèi)核中的一個(gè)內(nèi)部鏈表

一、定義

1、消息隊(duì)列是一種先進(jìn)先出的隊(duì)列型數(shù)據(jù)結(jié)構(gòu),實(shí)際上是系統(tǒng)內(nèi)核中的一個(gè)內(nèi)部鏈表。消息被順序插入隊(duì)列中,其中發(fā)送進(jìn)程將消息添加到隊(duì)列末尾,接受進(jìn)程從隊(duì)列頭讀取消息。
2、多個(gè)進(jìn)程可同時(shí)向一個(gè)消息隊(duì)列發(fā)送消息,也可以同時(shí)從一個(gè)消息隊(duì)列中接收消息。發(fā)送進(jìn)程把消息發(fā)送到隊(duì)列尾部,接受進(jìn)程從消息隊(duì)列頭部讀取消息,消息一旦被讀出就從隊(duì)列中刪除。

二、結(jié)構(gòu)

1、消息隊(duì)列中消息本身由消息類型和消息數(shù)據(jù)組成,通常使用如下結(jié)構(gòu):

struct msgbuf
{
	long 	mtype;
	char	mtext[1];
}

1)mtype指定了消息類型,為正整數(shù)。

引入消息類型之后,消息隊(duì)列在邏輯上由一個(gè)消息鏈表轉(zhuǎn)化為多個(gè)消息鏈表。發(fā)送進(jìn)程仍然無(wú)條件把消息寫入隊(duì)列的尾部,但接收進(jìn)程卻可以有選擇地讀取某個(gè)特定類型的消息中最接近隊(duì)列頭的一個(gè),即使該消息不在隊(duì)列頭。相應(yīng)消息一旦被讀取,就從隊(duì)列中刪除,其它消息維持不變。

2)成員mtext指定了消息的數(shù)據(jù)。我們可以定義任意的數(shù)據(jù)類型甚至包括結(jié)構(gòu)來(lái)描述消息數(shù)據(jù)。

例1 :定義消息結(jié)構(gòu),它的消息數(shù)據(jù)是一個(gè)整型數(shù)據(jù)。

struct msgbuf
{
	long 	mtype;
	int 	ntext;
};

例2:定義消息結(jié)構(gòu),它的消息數(shù)據(jù)是一個(gè)字符數(shù)組和一個(gè)整型數(shù)據(jù)。

struct msgbuf
{
	long 	mtype;
	char	ctext[100];
	int 	ntext;
};

例3:定義消息結(jié)構(gòu),它的消息數(shù)據(jù)是一個(gè)結(jié)構(gòu),該結(jié)構(gòu)由一個(gè)字符數(shù)組和一個(gè)整型數(shù)據(jù)組成。

struct msgtext
{
	char	ctext[200];	
    int 	ntext;
}
struct msgbuf
{
   long 	mtype;	
   struct  msgtext stext;
};

三、消息隊(duì)列的創(chuàng)建

1、在UNIX中,采用函數(shù)msgget創(chuàng)建消息隊(duì)列,原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);

函數(shù)創(chuàng)建一個(gè)新的消息隊(duì)列,或訪問(wèn)一個(gè)已經(jīng)存在的消息隊(duì)列。

1)參數(shù)key是消息隊(duì)列的關(guān)鍵字。

注:當(dāng)參數(shù)key取值IPC_PRIVATE時(shí),函數(shù)創(chuàng)建關(guān)鍵字為0的消息隊(duì)列。在UNIX內(nèi)核中雖然要求消息隊(duì)列關(guān)鍵字唯一,但也可以創(chuàng)建多個(gè)關(guān)鍵字為0的消息隊(duì)列。

2)參數(shù)msgflg的低9位指定隊(duì)列的屬主、屬組和其他用戶的訪問(wèn)權(quán)限,其它位指定消息隊(duì)列的創(chuàng)建方式。

創(chuàng)建方式參數(shù):

  • IPC_CREAT:創(chuàng)建,如存在則打開;
  • IPC_EXCL:與IPC_CREAT使用,單獨(dú)使用無(wú)意義。創(chuàng)建時(shí),如存在則失敗。

例1:創(chuàng)建關(guān)鍵字為0x1234,訪問(wèn)權(quán)限為0666的消息隊(duì)列,如隊(duì)列已存在返回其標(biāo)識(shí)號(hào)。

int msgid;
msgid = msgget(0x1234, 0666|IPC_CREAT);

例2:創(chuàng)建關(guān)鍵字為0x1234,訪問(wèn)權(quán)限為0666的消息隊(duì)列,如隊(duì)列已存在則報(bào)錯(cuò)。

int msgid;
msgid = msgget(0x1234, 0666|IPC_CREAT|IPC_EXCL);

四、消息隊(duì)列的發(fā)送與接收

類似于底層文件編程的函數(shù)read和write,函數(shù)msgsnd應(yīng)用于消息隊(duì)列的發(fā)送,函數(shù)msgrcv用于消息隊(duì)列的接收。

1、在UNIX中函數(shù)msgsnd向消息隊(duì)列發(fā)送消息,原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, void *msgp, int msgsz, int msgflg);

1)函數(shù)msgsnd向隊(duì)列消息msgid發(fā)送消息,相關(guān)參數(shù)的含義:

  • msgid:指定發(fā)送消息隊(duì)列的標(biāo)識(shí)號(hào);
  • msgp:指向存儲(chǔ)待發(fā)送消息內(nèi)容的內(nèi)存地址,用戶可設(shè)計(jì)自己的消息結(jié)構(gòu);
  • msgsz:指定長(zhǎng)度,僅記載數(shù)據(jù)的長(zhǎng)度,不包括消息類型部分,且必須大于0;
  • msgflg:控制消息發(fā)送的方式,有阻塞和非阻塞(IPC_NOWAIT)兩種方式。

2)導(dǎo)致msgsnd函數(shù)阻塞的原因:

  • 消息隊(duì)列滿:阻塞條件為msg_cbytes + msgsz > msg_qbytes;
  • (msg_cbytes:消息隊(duì)列中已使用字節(jié)數(shù);
  • msg_qbytes:消息隊(duì)列中可以容納的最大字節(jié)數(shù);)
  • 消息總數(shù)滿:系統(tǒng)中所有消息隊(duì)列記載的消息總數(shù)已達(dá)到系統(tǒng)上限值。

3)以阻塞方式向阻塞隊(duì)列(關(guān)鍵字為KEY)中寫入字符串“Helo UNIX!”,消息類型為TYPE。

全部過(guò)程分為5步:

第一步:定義消息結(jié)構(gòu)

struct msgbuf{	
	long mtype;		
	char ctext[100];
}	

第二步:打開消息隊(duì)列

int msgid;
msgid = msgget(KEY, 0666|IPC_CREAT);
if(msgid < 0)	//打開或創(chuàng)建消息失??;

第三步:組裝消息,設(shè)置消息類型和拷貝消息數(shù)據(jù)

struct msgbuf buf;
buf.mtype = 100;
strcpy(buf.ctext, “HELLO UNIX!”);

第四步:發(fā)送消息

int ret;
ret = msgsnd(msgid, &buf, strlen(buf.ctext), 0);

第五步:發(fā)送判斷

if(ret == -1)
{
	if(errno == EINTR)	//信號(hào)中斷,重新發(fā)送;
	else //系統(tǒng)錯(cuò)誤
}

進(jìn)程在發(fā)送消息過(guò)程中如果接收到信號(hào),將中止消息發(fā)送并返回EINTR錯(cuò)誤,此時(shí)重新發(fā)送即可。

2、實(shí)例:循環(huán)讀取鍵盤輸入,并將輸入的字符串寫入到消息隊(duì)列(關(guān)鍵字為0x1234)。

#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <sys/errno.h>
#include<string.h>

extern int errno;
struct mymsgbuf{
		long mtype;
		char ctext[100];
};
int main(){
		struct mymsgbuf buf;	
		int msgid;
		if((msgid = msgget(0x1234, 0666|IPC_CREAT)) < 0)	
		{
			fprintf(stderr, "open msg %x failed.\n", 0x1234);
			return;
		}
		while(strncmp(buf.ctext, "exit", 4))	
		{
			memset(&buf, 0, sizeof(buf));
			fgets(buf.ctext, sizeof(buf.ctext), stdin);
			buf.mtype = getpid();

			while((msgsnd(msgid, &buf, strlen(buf.ctext),0)) < 0)
			{
				if(errno == EINTR)
					continue;
				return;		
			}

		}
		return 0;
}

3、在UNIX中函數(shù)msgrcv從消息隊(duì)列中接收消息,原型:

#include <sys/types>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msgid, void *msgp, int msgsz, long msgtyp, int msgflg);

1)函數(shù)msgrcv從消息隊(duì)列msgid中讀取一條消息,參數(shù)含義:

  • msgid:消息隊(duì)列標(biāo)識(shí)號(hào);
  • msgp:指向接收消息的內(nèi)存緩沖區(qū);
  • msgsz:指定該緩沖區(qū)的最大容量,不包括消息類型占用的部分;
  • msgtyp:指定讀取消息的類型;

( 0:讀取消息隊(duì)列中第一個(gè)消息;

  • 正整數(shù):讀取消息隊(duì)列中第一個(gè)類型為msgtyp的消息;
  • 負(fù)整數(shù):讀取消息隊(duì)列中第一個(gè)類型小于或等于msgtyp的絕對(duì)值的消息。)
  • msgflg:指定了消息的接收方式
  • (IPC_NOWAIT:非阻塞方式讀取信息;
  • MSG_NOERROR:截?cái)嘧x取消息。)

2)以阻塞方式從消息隊(duì)列(關(guān)鍵字為KEY)接收消息,接收消息類型為TYPE。

第一步:定義消息結(jié)構(gòu)
一般要求與發(fā)送消息程序中定義結(jié)構(gòu)一致
第二步:打開(創(chuàng)建)消息隊(duì)列

int msgid;
msgid = msgget(KEY, 0666|IPC_CREAT);

第三步:準(zhǔn)備接收消息緩沖區(qū)

struct msgbuf buf;
memset(buf, 0, sizeof(buf));

第四步:接收消息

int ret;
ret = msgrcv(msgid, &buf, sizeof(buf.ctext), TYPE, 0);

第五步:接收判斷

if(ret == -1)
{
	if(errno == EINTR)	 //信號(hào)中斷,重新接收;
	else                 //系統(tǒng)錯(cuò)誤
}

4、實(shí)例:以阻塞方式不斷從消息隊(duì)列(關(guān)鍵字為0x1234)中讀取消息,并打印接收到的消息類型、長(zhǎng)度和數(shù)據(jù)等,當(dāng)接收到內(nèi)容為“exit”的消息時(shí)程序結(jié)束。

#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <sys/errno.h>
extern int errno;
struct mymsgbuf{
	long mtype;
	char ctext[100];
};
int main(){
	struct mymsgbuf buf;
	int msgid;	
	int ret;
	if((msgid = msgget(0x1234, 0666|IPC_CREAT)) < 0)	{
		fprintf(stderr, "open msg %X failed.\n", 0x1234);
		return;
	}
	while(strncmp(buf.ctext, "exit", 4))
	{
		memset(&buf, 0, sizeof(buf));
		while((ret = msgrcv(msgid, &buf, sizeof(buf.ctext), buf.mtype, 0)) < 0)
		{
			if(errno == EINTR)
				continue;
			return;
		}
		fprintf(stderr,"Msg:Type=%d,Len=%d,Text:%s",buf.mtype,ret, buf.ctext);
	}
	return 0;
}

綜合以上兩個(gè)實(shí)例:

五、小結(jié)

  • 1、采用消息隊(duì)列通信比采用管道通信具有更多的靈活性,通信的進(jìn)程不但沒(méi)有血緣上的要求,也不需要進(jìn)行同步處理。
  • 2、消息隊(duì)列是一種先進(jìn)先出的隊(duì)列型數(shù)據(jù)結(jié)構(gòu);
  • 3、消息隊(duì)列將輸出的信息進(jìn)行了打包處理,可以保證以消息為單位進(jìn)行接收;
  • 4、消息隊(duì)列對(duì)信息進(jìn)行分類服務(wù),根據(jù)消息的類別進(jìn)行分別處理。
  • 5、提供消息數(shù)據(jù)自動(dòng)拆分功能,同時(shí)不能接受兩次發(fā)送的消息。
  • 6、消息隊(duì)列提供了不完全隨機(jī)讀取的服務(wù)。
  • 7、消息隊(duì)列提供了完全異步的讀寫服務(wù)。

到此這篇關(guān)于C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)的文章就介紹到這了,更多相關(guān)C++消息隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Qt如何實(shí)現(xiàn)輸入框@聯(lián)系人的@檢測(cè)的示例

    Qt如何實(shí)現(xiàn)輸入框@聯(lián)系人的@檢測(cè)的示例

    本文主要介紹了Qt如何實(shí)現(xiàn)輸入框@聯(lián)系人的@檢測(cè)的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • C++實(shí)現(xiàn)LeetCode(39.組合之和)

    C++實(shí)現(xiàn)LeetCode(39.組合之和)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(39.組合之和),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器

    Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器

    計(jì)算器是我們生活中很常見(jiàn)的東西,它可以由多種語(yǔ)言多種方式來(lái)實(shí)現(xiàn)。本文主要介紹的是基于C++語(yǔ)言,由QT實(shí)現(xiàn)的可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器,需要的可以參考一下
    2022-12-12
  • C++實(shí)例輸入多行數(shù)字到數(shù)組

    C++實(shí)例輸入多行數(shù)字到數(shù)組

    這篇文章主要介紹了C++實(shí)例輸入多行數(shù)字到數(shù)組的相關(guān)資料,這里提供實(shí)例代碼幫助大家學(xué)習(xí)理解,需要的朋友可以參考下
    2016-12-12
  • gcc中extra qualification錯(cuò)誤的解決

    gcc中extra qualification錯(cuò)誤的解決

    今天小編就為大家分享一篇gcc中extra qualification錯(cuò)誤的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • 貪吃蛇C語(yǔ)言代碼實(shí)現(xiàn)(難度可選)

    貪吃蛇C語(yǔ)言代碼實(shí)現(xiàn)(難度可選)

    這篇文章主要為大家詳細(xì)介紹了貪吃蛇C語(yǔ)言代碼實(shí)現(xiàn),游戲難度可供選擇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 三種獲取網(wǎng)頁(yè)源碼的方法(使用MFC/Socket實(shí)現(xiàn))

    三種獲取網(wǎng)頁(yè)源碼的方法(使用MFC/Socket實(shí)現(xiàn))

    Windows下比較簡(jiǎn)單的獲取網(wǎng)頁(yè)源碼的方法:使用MFC、使用MFC、Socket實(shí)現(xiàn)
    2013-12-12
  • 舉例理解C語(yǔ)言二維數(shù)組的指針指向問(wèn)題

    舉例理解C語(yǔ)言二維數(shù)組的指針指向問(wèn)題

    這篇文章主要介紹了C語(yǔ)言二維數(shù)組的指針指向問(wèn)題,文中不建議用二級(jí)指針來(lái)訪問(wèn)二維數(shù)組,需要的朋友可以參考下
    2015-12-12
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇小游戲

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 淺析C++中的函數(shù)重載

    淺析C++中的函數(shù)重載

    這篇文章主要介紹了淺析C++中的函數(shù)重載,在C++中,可以為兩個(gè)或兩個(gè)以上的函數(shù)提供相同的函數(shù)名稱,只要參數(shù)類型不同,或者參數(shù)類型相同而參數(shù)個(gè)數(shù)不同,又或者參數(shù)類型參數(shù)個(gè)數(shù)相同,參數(shù)次序不同,稱為函數(shù)重載,需要的朋友可以參考下
    2023-08-08

最新評(píng)論