system V 进程间通信-------消息队列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_37964044/article/details/81589882

进程间通信,顾名思义就是进程和进程通信,也就是进程a和进程b可以访问内核的同一块空间一个放数据,一个取数据,那么这两个进程就完成通信通信了。

消息队列也有管道一样的不足:1.每个消息的最大长度是有上限的MSGMAX字节,每个消息队列的总字节数是有上限的MSGMNB,系统中消息队列的总数是有上限的MSGMNI

如何查看:

cat   /proc/sys/kernel/msgmax

cat   /proc/sys/kernel/msgmni

cat   /proc/sys/kernel/msgmnb

消息队列:提供了一个进程向另一个进程发送有类型数据块的方法,实现通信。a进程往消息队列里面发有不同类型的数据块,b进程可以从消息队列中取不同类型的数据块

b

创建或者打开一个消息队列

用来创建/打开一个消息队列
函数原型:
int msgget(key_t key,int msgflag)
参数:key 表示消息队列的名字,通过key值可以找到消息队列,相当于open打开文件时的文件描述符
      msgflag  1.如果是创建文件IPC_CREAT|0644权限  2.如果是打开一个消息队列填0
返回值:成功返回消息队列的id,失败返回-1

key一个ipc对象的唯一标识,可以通过ftok生成

往消息队列里面发送数据

往消息队列中添加一个数据块,也就是往消息队列中添加一条消息
函数原型:
int msgsnd(int msgid,const void*msg,size_t msgsz,int msgflag)
参数:msgid是消息队列id,也就是msgget成功的返回值
      msg要发送的消息在哪儿
	  msgsz要发送消息的字节数
	  msgflag默认给为0(表示装满了,阻塞) , 也可以设置为装满了报错退出,此处不关心
返回值:成功0 失败-1

注意:

一   发送的消息结构在两方面受到制约

1.必须小于系统规定的上限值

2.必须以一个长整数开始,接受者函数将通过这个长整数确定消息的类型

二  消息结构参考形式如下

struct msgbuf
{
	long mtype;//消息类型(类型号必须>=1
	char mtext[1];//自己写的消息,随便定义
};

三 msgsnd的第三个参数长度不包括上面所说的类型长度

从消息队列中取数据

从一个消息队列中接收数据
函数原型:
ssize_t msgrcv(int id,void* msgp,size_t msgsz,long msgtyp,int msgflg)
参数: id :消息队列id
       msgp:指向准备接受的消息,也就是取出来的消息放在哪
       msgsz :msgp指向的消息长度,这个长度也不包含消息类型长度
	   msgtyp:表示取哪个类型的消息    >0只读取特定类型数据   =0按照先进先出的顺序读取   <0变成优先级队列 出满足类型小于等于msgtyp的第一条消息
	   msgflg:1.设置为0 阻塞     2.也可以设置为非阻塞 有就取,没有出错返回
返回值:失败返回-1,成功返回实际放到缓冲区里面的字符个数

删除消息队列

删除消息队列
函数原型:
int msgctl(int msgid, int cmd,struct msgid_ds*buf)
参数:msgid:消息队列id
      cmd:取值为IPC_RMID表示删除消息队列
      buf:不关心给0
返回值:成功返回0,失败返回-1

除了用上面接口删除一个消息队列也可以用命令

消息队列常用的命令

ipcs------查看所有ipc对象(消息队列  共享内存 信号量)

ipcs -q   查看消息队列

ipcrm -Q key  删除消息队列

ipcrm -q msgid

消息队列的缺点:

1.发有类型的数据,取有类型的数据

2.系统中能创建的消息队列有上限,每个消息队列能装的内容有限

3.每一次访问消息队列要调用操作系统提供的接口函数,从用户切到内核,由内核切到用户,开销太大

消息队列的特点:

1.能够应用于任意进程之间

2.双向通信

3.面向数据块

4.内置同步互斥机制,多个进程读写不会出错

5.生命周期随内核

底下附上简单实现的代码:

msgget.c

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

int main()
{
 int msgid=  msgget(1234,IPC_CREAT|0666);
 if(msgid==-1)
 {
  perror("msgget");
  exit(-1);
 }
 printf("msgget is ok\n");
}

msgrcv.c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
struct msgbuf
{
    long mtype;
    char mtext[100];

};
int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        printf("Usage:%s type\n",argv[0]);
        exit(1);
    }
    int id=msgget(1234,0);
    if(id==-1)
    {
        exit(-1);
    }
 struct msgbuf mb;
 if( msgrcv(id,&mb,100,argv[1],0)==-1 )
   {
     exit(-1);
   }

     printf("%s\n",mb.mtext);
}

msgsnd.c

#include<sys/ipc.h>
#include<sys/msg.h>
struct msgbuf
{
    long mtype;
    char mtext[100];

};
int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        printf("Usage:%s type\n",argv[0]);
        exit(1);
    }
    int id=msgget(1234,0);
    if(id==-1)
    {
        exit(-1);
    }
    struct msgbuf mb;
    mb.mtype=atoi(argv[1]);
    printf("msg:");
    fgets(mb.mtext,99,stdin);
    int r=msgsnd(id,&mb,strlen(mb.mtext),0);
    if(r==-1)
    {

        perror("msgsnd");
    }


}

猜你喜欢

转载自blog.csdn.net/baidu_37964044/article/details/81589882