进程间通信(IPC)------消息队列

1、消息队列

  有一个队列,队列中存放各种消息。每个进程都可以把数据封存在消息中,再放入队列。
  每个进程都可以拿到消息队列,再从中取出/放入消息。
  消息队列不会产生覆盖问题,但需要考虑队列长度。

消息队列的编程步骤:
  1 生成key,使用ftok()或用头文件定义
  2 创建/获取消息队列 msgget()
  3 发送/接收消息 msgsnd() / msgrcv()
  4 如果不会再被使用(所有进程都不用)可以删除
    msgctl()

相关函数:
msgget()用法和shmget()基本一样。获取时flag为0,新建时flag为 权限|IPC_CREAT|IPC_EXCL
msgctl()用法和shmctl()基本一样。

int msgsnd(int msgid,void* p,size_t size,int flag)
msgid 就是消息队列,p是发送的消息的首地址,size是发送消息的大小,flag为0代表阻塞,为IPC_NOWAIT代表非阻塞。(消息满了以后是否等待)
成功返回0,失败返回-1

ssize_t msgrcv(int msgid,void* buf,size_t size,int msgtype,int flag)
msgid、flag和msgsnd()一样
buf是用来接收消息的首地址
size是sizeof(buf)
msgtype 代表消息的类型,消息分为:
  无类型消息和有类型消息

1、无类型消息

msga.c

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

int main()
{
    key_t key = ftok(".",100);
    if(key==-1)
    { 
        perror("ftok");
         exit(-1);
    }
    int msgid = msgget(key,
        0666|IPC_CREAT|IPC_EXCL);
    if(msgid==-1) 
    {
        perror("msgget");
        exit(-1);
    }
    int res = msgsnd(msgid,"hello",5,0);
    if(res==-1)
    {
     perror("msgsnd");
     exit(-1);
    }
    printf("send ok\n");
}//练习:写msgb.c,从消息队列中取出hello并打印

----------------------------------------------------------

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

int main()
{
    key_t key = ftok(".",100);
    if(key==-1)
    {
        perror("ftok");
        exit(-1);
    }
    int msgid = msgget(key,0);
    if(msgid==-1)
    {
        perror("msgget");
        exit(-1);
    }
    char buf[100] = {};
    int res = msgrcv(msgid,buf,sizeof(buf),0,0);
    if(res==-1) 
    {
        perror("msgrcv");
        exit(-1);
    }
    printf("buf=%s,rcv=%d\n",buf,res);
}

无类型消息可以是任意类型,比如:整数、字符串、浮点…
无类型消息的取出遵循队列的基本准则: FIFO。

2、有类型消息

有类型消息,类型必须是一个结构体:
  struct 自定义名字{
    long mtype;//消息类型,必须有,格式固定
    char msg[];//数据
  };
数据是:char数组,长度和名称可以自定义,用其他类型也可以
mtype取值时,必须 大于0。(赋值时不能<=0)
接收数据时可以按消息类型接收,msgrcv()中的第四个参数可以指定接收消息的类型:
= 0 代表接收任意类型的消息(遵循先入先出)
大于 0 代表接收特定类型的消息(mtype=值)
<0 代表接收类型小于等于参数绝对值的消息
次序从小到大,如果类型相同,按在队列中的位置

这里写图片描述
有类型消息在计算发送和接收的size时,可以不计算类型所占的空间。(sizeof(struct)-4)。发送和接收要么都计算,要么都不计算。

msgtypea.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct mymsg
{
    long mtype; //类型
    char buf[256];// 数据
};

int main(){
    key_t key = ftok(".",100);
    int msgid = msgget(key,0666|IPC_CREAT);
    if(msgid==-1) 
    {
        perror("msgget");
        exit(-1);
    }
    struct mymsg msg1 = {1,"hello1"};
    struct mymsg msg2 = {2,"hello2"};
    int res1 = msgsnd(msgid,&msg1,
            sizeof(msg1)-4,0);
    int res2 = msgsnd(msgid,&msg2,
            sizeof(msg2)-4,0);
    if((res1==0)&&(res2==0))printf("send ok\n");
}

----------------------------------------------------------

msgtypeb.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct mymsg
{
    long mtype; //类型
    char buf[256];// 数据
};

int main()
{
    key_t key = ftok(".",100);
    int msgid = msgget(key,0);
    if(msgid==-1) 
    {
        perror("msgget");
        exit(-1);
    }
    struct mymsg msg;
    int res = msgrcv(msgid,&msg,sizeof(msg)-4,
        -2,0);
    if(res==-1) 
    {
        perror("msgrcv");
        exit(-1);
    }
    printf("mtype=%ld,msg=%s\n",msg.mtype,
            msg.buf);
}

猜你喜欢

转载自blog.csdn.net/qq_35433716/article/details/81659886