消息队列——进程间通信方式

一、概念
消息队列是由存放在内核中由消息组成的链表,由IPC id标识。用户可以在消息队列中添加和读取消息。

特点:

1.消息队列提供的是一种带有数据标识的特殊管道,因此可以选择性的读取信息;
2.如果消息队列中有多条类型一样的消息,接收的时候只能按照先后顺序接收(队列特点);
3.如果你接收的消息类型不存在,接收会阻塞。

1.创建IPC键值
创建IPC之前必须获取一个未使用的IPC键值(key);

#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
参数:1.pathname必须是一个已经存在的目录
	 2.proj_id项目表符是一个8位,1个字节的值,通常用字母a,b表示。

2.获取消息队列ID

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

参数:1.KEY,消息队列的键值,可以使用ftok获得或者使用IPC_PRIVATE
	 2.msgflg可以为IPC_CREAT、IPC_EXCL、IPC_NOWAIT或者三者的结果
1>IPC_CREAT:若内核中不存在指定队列就创建它,第二个参数还需要与文件权限一起使用,例如
IPC_CREAT|00666表示若内核中不存在指定队列则创建它,同时进程可以对队列消息进行读写操作。;
2>IPC_EXCL:当与IPC_CREAT一起使用时,若队列已存在则出错(函数返回-1)

3.发送消息到消息队列中

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

参数:1.消息队列的id
	 2.指向消息缓冲区,发送消息必须把消息打包成结构体
struct msg
{
	long msgtype;  //消息类型
	char msgdata[size]; //存放真实信息
};

	 3.消息的长度
	 4.message flag,可设置为0和IPC_NOWAIT,标志为**IPC_NOWAIT**,表示msgsnd操作以非阻塞的方式进行,在消息队列中没有可用的空间时,msgsnd操作会立刻返回。并指定EAGAIN错误;
标志为**0**,表示msgsnd操作以阻塞的方式进行,这种情况下在消息队列中没有可用的空间时调用线程会被阻塞,直到下面的情况发生:

4.从消息队列中读取消息

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

参数1:msqid-消息队列的id
   2:msgp-指向消息缓冲区
   3:消息的大小
   4:指定要从队列中获取的消息类型,若取0,任意类型都接收

5.消息队列的删除、属性设置和获取控制等操作

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

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

参数1:msqid-消息队列的id
   2:控制操作的命令,SUS标准提供以下三个命令
**IPC_RMID**,删除一个消息队列。执行该命令系统会立刻把该消息队列从内核中删除,该消息队列中的所有消息将会被丢弃。
**IPC_SET**,根据buf的所指的值来设置消息队列msqid_ds结构中的msg_perm.uid,msg_perm.gid,msg_perm.mode,msg_qbytes四个成员。
**IPC_STAT**,通过buf返回当前消息队列的msqid_ds结构。
    3.buf:指向msqid_ds结构的指

6.系统V消息队列的限制
在这里插入图片描述
系统范围内的最大消息数,在Linux下这个限制由msgmnb*msgmni决定。
可以通过IPC_SET来设置使用中的消息队列的最大字节数。但是要在系统范围内对内核限制进行修改,在Linux下面可以通过修改**/etc/sysctl.conf内核参数配置文件,然后配合sysctl**命令来对内核参数进行设置。

二、程序demon

发送端

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/msg.h>
#include<errno.h>
#include<string.h>

#define MAX 1024
 
struct msg
{
	long msgtype;  //消息类型
	char msgdata[MAX]; //存放真实信息
};

 
int main()
{
   int running =1;
   struct msg data;
   char buffer[BUFSIZ];//BUFSIZ的值等于一个常量值,这个值是8192,一般是会用来做数组的长度
   printf("bufsiz size is %d\n",BUFSIZ);
   printf("MAX is %d\n",MAX);
   int msgid=-1;
   msgid=msgget((key_t)66666,0666|IPC_CREAT);
   if(msgid==-1)
   {
    	perror("msgget");
   }
   printf("===misgid is %d\n",msgid);
   while(running)
   {
      printf("input msg:");
      fgets(buffer,BUFSIZ,stdin);
      data.msgtype=2;
      strcpy(data.msgdata,buffer);
      if(msgsnd(msgid,(void *)&data,MAX,0)==-1)
      {
        perror("msgsnd");
      }
      if(strncmp(buffer,"quit",3)==0)
          running=0;
  }
      printf("exit success");
      exit(EXIT_SUCCESS);
}

读取信息端

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<sys/stat.h>

#define MAX 1024
 
struct msg
{
	long msgtype;  //消息类型
	char msgdata[MAX]; //存放真实信息
};

int main()
{
  int running =1;
  int msgid=-1;
  struct msg data;
  long int msgtype=0;
  msgid=msgget((key_t)66666,0666|IPC_CREAT);
  if(msgid==-1)
  {
     perror("msgget");
  }
  while(running)
  {
    if(msgrcv(msgid,(void *)&data, BUFSIZ,msgtype,0)==-1)
    {
        perror("msgrcv");
    }
    printf("rcv data msg_type is %ld\n",data.msgtype);
    printf("msg is :%s\n",data.msgdata);
    if(strncmp(data.msgdata,"quit",4)==0)
        running=0;
  }
  if(msgctl(msgid,IPC_RMID,0)==-1)
  {
     perror("msgctl");
  }
  exit(EXIT_SUCCESS);
}

运行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值