linux进程间通信—消息队列

消息队列
(一)消息队列提供了从一个进程向另一个进程发送数据块,每个数据块都有一个类型,接收进程可以独立的接收含有不用类型的数据结构,可以通过发送消息来避免命名管道的同步和阻塞问题,但是消息队列和命名管道一样,每个数据块都有最大长度。
(二)特点:
1.消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取,编程时可以按照消息的类型读取。
2.消息队列允许一个或者多个进程向其读取或者写入数据
3.与匿名管道和命名管道一样,从消息队列中读出数据,消息队列中对应的数据都会被删除。
4.每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的。
5.消息队列是消息的链表,存放在内存中,由内核维护,只有内核重启或者人工删除消息队列时,该消息队列才会被删除,否则会一直存在于系统中。
(三)常用函数:
1.键(key)值
(1)所需头文件

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

(2)函数:key_t ftok(const char* pathname,int proj_id);//获取键值
(3)参数:

  • pathname:路径名
  • proj_id:项目ID,非零整数(只有低八位有效)

(4)返回值

  • 成功:key值
  • 失败:-1

1.消息队列的创建
(1)所需头文件:

#include <sys/msg.h>

(2)函数:

int msgget(key_t key,int msgflg);//创建一个新的或者打开一个已存在的消息队列,不用的进程调用此函数,只需要用相同的key值就能得到同一个消息队列的标识符。

(3)参数:

  • key:ftok()返回的key值
  • msgflg:标识函数的行为以及消息队列的权限,其取值如下:
  • IPC_CREAT:创建消息队列
  • IPC_EXCL:检测消息队列是否存在
    (4)返回值:
  • 成功:消息队列的标识符
  • 失败:-1

实例代码:

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

int main()
{
  key_t key;
  int msgid;
  key = ftok(".",2019);
  if(key == -1)
  {
    perror("ftok error");
  }
  msgid = msgget(key,IPC_CREAT);
  if(msgid<0)
  {
    perror("msgget error");
  }
  return 0;
}

运行结果:
在这里插入图片描述
3.添加消息
(1)所需头文件:

#include <sys.msg.h>

(2)函数:

int msgsnd(int msqid,const void* msgp,size_t msgsz,int msgflg);//将新消息添加到消息队列

(3)参数:

  • msqid:消息队列的标识符
  • msgp:带发送消息结构体的地址
  • msgsz:消息正文的字节数
  • msgflg:函数的控制属性,取值如下:
  • 0:msgsnd()调用阻塞知道条件满足为止
  • IPC_NOWAIT:若消息没有立即发送则调用该函数的进程立即返回

(4)返回值:

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

4.获取消息
(1)所需头文件:

#include <sys/msg.h>

(2)函数:

ssize_t msgrcv(int msqid,void* msgp,size_t msgsz,long msgtyp,int msgflg);//从标识符为msqid的消息队列中接收一个消息,一旦接受成功,则消息在消息队列中被删除。

(3)参数:

  • msqid:消息队列的标识符
  • msgp:存放消息结构体的地址
  • msgsz:消息正文的字节数
  • msgtyp:消息的类型,类型如下:
  • msgtyp = 0:返回队列中的第一个消息
  • msgtyp > 0:返回队列中消息类型为msgtyp的消息(常用)
  • msgtyp < 0:返回队列中消息类型值小于或者等于msgtyp绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
    注意:在获取某类型消息的时候,若队列中有多条此类型的消息,则获取最先添加的消息,即先进先出的原则
  • msgflg:函数的控制属性。其取值如下:
  • 0:msgrcv()调用阻塞知道接收消息成功为止
  • MSG_NOERROR:若返回的消息字节数比nbytes字节数多,则消息就会截断到nbytes字节,先不通知消息发送进程
  • IPC_NOWAIT:调用进程会立即返回。若没有收到消息则立即返回-1

(4)返回值:

  • 成功:读取消息的长度
  • 失败:-1

5.消息队列的控制
(1)所需头文件:

#include <sys/msg.h>

(2)函数:

int msgctl(int msqid,int cmd,struct msqid_ds *buf);//对消息队列进行控制,如修改消息队列的属性,或者删除消息队列

(3)参数:

  • msqid:消息队列的标识符
  • cmd:函数功能的控制,取值如下:
  • IPC_RMID:删除标识符为msqid的消息队列,将它从系统中删除并破坏其相关数据结构
  • IPC_STAT:将msqid相关的数据结构中各个元素的当前值存入由buf指向的结构中,相当于把消息队列的属性备份到buf中
  • IPC_SET:将msqid相关的数据结构中元素设置为由buf指向的结构中的对应值,相当于消息队列原来的属性值清空,再由buf替换
  • buf:msqid_ds数据类型的地址,用来存放或者更该消息队列的属性。

(4)返回值:

  • 成功:0
  • 失败:-1

(四)实例
描述:
write.c

#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <string.h>
typedef struct MSG
{
  long mType;
  char mData[1024];
}MSG;

int main()
{
  MSG msg;
  key_t key;
  int msqid;
  key = ftok(".",2019);
  if(key == -1)
  {
    perror("ftok error");
  }
  msqid = msgget(key,IPC_CREAT|0666);
  if(msqid<0)
  {
    perror("msget error");
  }
  msg.mType = 10;
  strcpy(msg.mData,"hello world");
  msgsnd(msqid,&msg,sizeof(MSG)-sizeof(long),0);
  return 0;
}

read.c

#include <sys/msg.h>
#include <stdio.h>
#include <string.h>

typedef struct MSG
{
  long mType;
  char mData[1024];
}MSG;

int main()
{
  key_t key;
  int msqid;
  key = ftok(".",2019);
  MSG msg;
  if(key == -1)
  {
    perror("ftok error");
  }

  memset(&msg,0,sizeof(msg));
  msqid = msgget(key,IPC_CREAT|0666);
  if(msqid<0)
  {
    perror("msgget error");
  }
  msgrcv(msqid,&msg,sizeof(msg)-sizeof(long),(long)10,0);

  printf("%s\n",msg.mData);
  
  msgctl(msqid,IPC_RMID,NULL);
  return 0;
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值