系统编程之进程间的消息队列通信(5)

系列文章目录

第一章 系统编程之多进程

第二章 系统编程之进程间的 管道 通信(1)

第二章 系统编程之进程间的 信号 通信(2)

第二章 系统编程之进程间的 共享内存 通信(3)

第二章 系统编程之进程间的 信号量 通信(4)

第二章 系统编程之进程间的 消息队列 通信 (5) 

一、消息队列

1、消息队列的原理

  • 消息队列是一种先进先出的队列型数据结构,实际上是系统内核中的一个内部链表。消息被顺序插入队列中,其中发送进程将消息添加到队列末尾,接受进程从队列头读取消息。
  • 多个进程可同时向一个消息队列发送消息,也可以同时从一个消息队列中接收消息。发送进程把消息发送到队列尾部,接受进程从消息队列头部读取消息,消息一旦被读出就从队列中删除。

查看消息队列:                ipcs  -q        

删除消息队列:                ipcrm  -q  消息队列的ID号

2、结构体定义

消息队列中消息本身由消息类型和消息数据组成,通常使用如下结构。

struct  msg                              

{                                      

        long mtype;        //消息类型

        char mtext[1];     //真实的信息                              

}

3、相关的接口函数

 (1)申请创建消息队列

#include <sys/msg.h>                      

int msgget(key_t key, int msgflg);                              

返回值:成功 返回消息队列的ID                                          

              失败 -1                                

key :键值

msgflg                                          

        IPC_CREAT :
                如果消息队列对象不存在,则创建之,否则则进行打开操作;
        IPC_EXCL:
                和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个错误并返回。如果单独使用IPC_CREAT 标志,msgget()函数要么返回一个已经存在的消息队列对象的标识符,要么返回一个新建立的消息队列对象的标识符。

(2)通过消息队列收发信息

发送信息:
把发送的信息打包成结构体
struct  msg
{
       //消息类型
       //真实的信息
}
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
返回值:成功 0  失败 -1
参数:msgp --》你要发送的信息
           msgsz --》你打算发送多少字节的数据
           msgflg --》默认设置为0
           msgsnd(id,"hello",5,0);
           msgsnd(id,"hehe",4,0);
           msgsnd(id,"china",5,0);   //错误的写法,原因信息没有打包成结构体(结构体包含了消息的类型)
                   

接收信息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
返回值:成功返回接收的字节数   失败 -1
参数:msgtyp(重点,重点,重点)  --》你要接收的消息类型
           其它参数跟msgsnd类似

(3)删除,获取,设置消息队列的属性

int msgctl(int msqid, int cmd, struct msqid_ds *buf);   

返回值:成功0  失败返回-1 

参数--》msgqid:是消息队列对象的标识符。
             cmd:消息队列进行的操作:
                        IPC_STAT:取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构中。
                        IPC_SET:设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds结构给出。
                        IPC_EMID:将队列从系统内核中删除。
                        IPC_STAT:将信息从与msqid关联的内核数据结构复制到buf指向的msqid_ds结构中。调用方必须对消息队列具有读取权限
 

struct msqid_ds {
     struct ipc_perm msg_perm;     /* Ownership and permissions */
     time_t          msg_stime;    /* Time of last msgsnd(2) */
     time_t          msg_rtime;    /* Time of last msgrcv(2) */
     time_t          msg_ctime;    /* Time of last change */
     unsigned long   __msg_cbytes; /* Current number of bytes in queue (nonstandard) */
     msgqnum_t       msg_qnum;     /* Current number of messages in queue */
     msglen_t        msg_qbytes;   /* Maximum number of bytes allowed in queue */
     pid_t           msg_lspid;    /* PID of last msgsnd(2) */
     pid_t           msg_lrpid;    /* PID of last msgrcv(2) */

};


4、使用实例 

(1)发送端代码

#include "myhead.h"
//自定义一个结构体存放要发送的信息和类型
struct msg
{
	long msgtype;  //消息类型
	char msgdata[50]; //存放真实信息
};
int main()
{
	int msgid;
	//申请创建消息队列
	msgid=msgget(74545,IPC_CREAT|IPC_EXCL|0777);
	if(msgid==-1)
	{
		if(errno==EEXIST)
		{
			msgid=msgget(74545,0777);
		}
		else
		{
			perror("创建失败!\n");
			return -1;
		}
	}
	
	//组包发送信息给接收端
	struct msg msg1;
	bzero(&msg1,sizeof(msg1));
	msg1.msgtype=999;
	strcpy(msg1.msgdata,"hello");
	msgsnd(msgid,&msg1,sizeof(msg1),0);
	
	struct msg msg2;
	bzero(&msg2,sizeof(msg2));
	msg2.msgtype=999;
	strcpy(msg2.msgdata,"world");
	msgsnd(msgid,&msg2,sizeof(msg2),0);
	
	struct msg msg3;
	bzero(&msg3,sizeof(msg3));
	msg3.msgtype=999;
	strcpy(msg3.msgdata,"gec");
	msgsnd(msgid,&msg3,sizeof(msg3),0);
	
}

(2)接收端代码

#include "myhead.h"
//自定义一个结构体存放要发送的信息和类型
struct msg
{
	long msgtype;  //消息类型
	char msgdata[50]; //存放真实信息
};
int main()
{
	int msgid;
	//申请创建消息队列
	msgid=msgget(74545,IPC_CREAT|IPC_EXCL|0777);
	if(msgid==-1)
	{
		if(errno==EEXIST)
		{
			msgid=msgget(74545,0777);
		}
		else
		{
			perror("创建失败!\n");
			return -1;
		}
	}
	
	//接收发送端发送过来的信息
	struct msg msg1;
	bzero(&msg1,sizeof(msg1));
	
	//msgrcv(msgid,&msg1,sizeof(msg1),777,0);
	msgrcv(msgid,&msg1,sizeof(msg1),999,0);
	printf("接收的信息:%s\n",msg1.msgdata);
	
	bzero(&msg1,sizeof(msg1));
	msgrcv(msgid,&msg1,sizeof(msg1),999,0);
	printf("接收的信息:%s\n",msg1.msgdata);
	
	bzero(&msg1,sizeof(msg1));
	msgrcv(msgid,&msg1,sizeof(msg1),999,0);
	printf("接收的信息:%s\n",msg1.msgdata);
	
}

总结

以上就是本文要介绍的内容,本文仅仅简单介绍了消息队列的原理和使用实例

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值