进程间通讯—消息队列

消息队列

   消息:由数据  && 类型 组成

   队列:学过数据结构我们知道,队列的特点是先进先出。

   消息队列:是种临时存储消息的队列,完成进程间数据传送,可以按照队列的特点和消息的类型优先传送数据。

   特点:

(1)与信号量相比,都以内核对象来确保多进程访问同一个消息队列,信号量控制进程间同步,而消息队列发送数据。

(2)与管道相比,管道发送的数据没有类型,读取数据端 无差别从管道中按照数据的前后顺序读取数据,消息队列的数据有类型,读端可以通过消息队列的类型读取特定的数据。


消息队列的创建或获取

1 、   #include<sys/msg.h>
       int msgget(key_t key,int flag)

  key_t  key 为键值,用户可以随意给一个long类型,然后转成key_t。
  flag  权限加 标志,创建消息队列时,指定IPC_CREATE,不用向信号量那样必须初始化,因为消息队列本身就带有消息的信息。成功返回消息队列ID  msgid,失败返回-1.

2、发送消息,将消息放到消息队列中,消息总是放在队列尾端。
       
int msgsnd(int msgid,  const  void*ptr,size,int flag)
      msgid就是消息队列ID
      ptr就是指向mymesg结构体的指针,也就是指向消息的指针
      size就是消息实际内容的字节数,也就是mymesg的第二个成员。
      flag 用来控制一些特殊的操作,比如flag可以设为IPC_NOWAIT,指明消息队列没有足够的空间容纳要发送的消息时,msgsnd是否等待。一般我们设为0就好了。

3、 int msgrcv(int msgid,struct mymesg_ds *buf,int size,long type,int flag)
     第一个参数就不多说了,第二个参数系统内核为每一个队列的当前状态设了相关联的结构体。
     size就是消息实际内容的字节数,也就是mymesg的第二个成员。
     long type 这个参数重要了,当你想获取1000这个类型的消息,就会优先读取1000这个类型消息的内容。
     flag参数同上个函数是一样的

4、 int   msgctl(int msgid ,int cmd,struct msgid_ds *buf)
     cmd参数:如果你想删除消息,cmd为IPC_RMID,最后一个参数设为0就好了。
    还有两个cmd参数:IPC_STAT取此队列的msgid_ds,并存放在buf指向的结构中
    IPC_SET 按由buf指向结构体中的值,设置与此队列相关结构体的成员。

我们看个例子,就知道消息队列到底是怎么传送数据的。

A进程负责根据用户选择的数据类型(long)发送,用户输入的数据(char*)
B进程读取1000类型的数据
C进程读取2000类型的数据

我们利用main函数可以传参把B、C进程写成一个程序。
A进程:
#include<stdio.h>
#include<assert.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/msg.h>
#include<sys/ipc.h>
#include<sys/types.h>

struct mymesg
{
    long type;
    char mtext[512];
}mymesg;

int main()
{
	
    int msgid=msgget((key_t)1234,0664|IPC_CREAT);
	
     assert(msgid!=-1);
     struct mymesg ptr;ptr.type=1000;
     ptr.mtext[512];
     strcpy(ptr.mtext,"hello");
     if(msgsnd(msgid,&ptr,512,IPC_NOWAIT)==-1)
    {
	perror("error\n");
        exit(0);
    }
    
    ptr.type=2000;
    strcpy(ptr.mtext,"world");
    if(msgsnd(msgid,&ptr,512,IPC_NOWAIT)==-1)
   {
	perror("error");
	exit(0);
   }
}
B、C进程

#include<stdio.h>
#include<assert.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/msg.h>
#include<sys/ipc.h>
#include<sys/types.h>


struct mymesg
{
    long type;
    char mtext[512];
};
int main(int argc,char*argv[])
{
	char buff[128]={0};
	struct mymesg ptr;
     int msgid=msgget((key_t)1234,0664|IPC_CREAT);
	assert(msgid!=-1);
      if(argc<=1)
	{
	    perror("few option\n");
	    exit(0);
	}
     sscanf(argv[1],"%d",&ptr.type);
     if(msgrcv(msgid,&ptr,512,ptr.type,0)!=-1)
	{
	    printf("%s\n",ptr.mtext);
	}
    
    /*if(msgctl(msgid,IPC_RMID,0)==-1)
     	{
	    perror("error\n");
	    exit(0);
	 }等读完消息队列的数据,再删了消息队列,否则只能读一次哦*/

}


运行结果:



扫描二维码关注公众号,回复: 908418 查看本文章








猜你喜欢

转载自blog.csdn.net/lyt15829797751/article/details/78392427