进程间通信之消息队列

声明:侵删

1.消息队列概述

消息队列是System V IPC对象的一种 存放在内存中由内核来维护

消息队列由消息队列ID来唯一标识

消息队列就是一个消息的链表。用户可以在消息队列中添加消息、读取消息

消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法,并且每一块数据块都有一个类型

消息队列可以按照类型来发送/接收消息

与管道一样,消息队列中数据被读取会删除 管道必须先进先出 而消息队列不用遵循

消息队列在内核中的表
在这里插入图片描述
消息队列使用步骤
①打开/创建消息队列 msgget

② 向消息队列发送消息 msgsnd

③从消息队列接收消息 msgrcv

④控制消息队列 msgctl

发送消息必须确定消息格式
通信双方首先定义好统一的消息格式

用户根据应用需求定义结构体类型

首成员类型为long,代表消息类型(正整数)

其他成员都属于消息正文

2.消息队列相关函数

打开创建消息队列 msgget函数
在这里插入图片描述
发送消息 msgsnd函数
在这里插入图片描述接收消息 msgrcv函数
在这里插入图片描述消息队列控制 msgctl函数
在这里插入图片描述

3.实例程序

消息发送端

/*msgsnd.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define IPC_PATH "/"
#define IPC_PRJ 1
#define MSG_TXT_SIZE 512
#define MSG_LEN sizeof(MSG)-sizeof(long)
typedef struct 
{
    long msg_type;
    char msg_txt[MSG_TXT_SIZE];
}MSG;

int main()
{
    key_t  msg_key;
    int msg_id;
    MSG    msg;
    /*创建消息队列的KEY*/
    if((msg_key = ftok(IPC_PATH,IPC_PRJ)) < 0)
    {
        perror("ftok");
        exit(-1);
    }
    /*创建消息队列,获取消息队列ID*/
    if ((msg_id = msgget(msg_key,IPC_CREAT|0666)) < 0)
    {
        perror("msgget");
        exit(-1);
    }
    system("ipcs -q ");
    /*获取终端输入信息,向消息队列发消息*/
    while(1)
    {
        printf("Please Enter Message TO Queue\n");
        if(fgets(msg.msg_txt,MSG_TXT_SIZE,stdin) < 0)
        {
            perror("fets");
            exit(-1);
        }
        msg.msg_type = getpid(); /*将消息类型设置为当前进程ID*/
        if(msgsnd(msg_id,&msg,MSG_LEN,0) < 0) /*堵塞*/
        {
            perror("msgsnd");
            exit(-1);
        }
        if (strncmp(msg.msg_txt,"quit",4) == 0)
        {
            break;
        }
    }
    /*删除消息队列*/
    if(msgctl(msg_id,IPC_RMID,NULL) < 0 )
    {
        perror("msgctl");
        exit(-1);
    }

    exit(0);
}

消息接收端

/*msgrcv.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define IPC_PATH "/"
#define IPC_PRJ 1
#define MSG_TXT_SIZE 512
#define MSG_LEN sizeof(MSG)-sizeof(long)
typedef struct 
{
    long msg_type;
    char msg_txt[MSG_TXT_SIZE];
}MSG;

int main()
{
    key_t  msg_key;
    int msg_id;
    MSG    msg; /*存放接收消息内容*/
    /*创建消息队列的KEY*/
    if((msg_key = ftok(IPC_PATH,IPC_PRJ)) < 0)
    {
        perror("ftok");
        exit(-1);
    }
    /*创建消息队列,获取消息队列ID*/
    if ((msg_id = msgget(msg_key,IPC_CREAT|0666)) < 0)
    {
        perror("msgget");
        exit(-1);
    }
    system("ipcs -q "); /*获取消息队列消息,向终端打印*/
   
   
    do
    {
        memset(msg.msg_txt,0,MSG_TXT_SIZE); /*将信号接收区清空*/
        if (msgrcv(msg_id,&msg,MSG_TXT_SIZE,0,0) < 0 ) /*将类型设置为0
                                                        接收消息队列中的第一个消息
                                                        最后一个参数 0 堵塞模式*/
        {
            perror("msgrcv");
            exit(-1);
        } 
        printf("The message from process[%ld]:%s\n",msg.msg_type,msg.msg_txt);
    } while (strncmp(msg.msg_txt,"quit",4) != 0);
    
    system("ipcs -q");
    printf("message queue was delete\n");

    exit(0);
}

结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值