进程间通信--消息队列

本文详细介绍了消息队列在Linux系统中的使用,包括无名管道和有名管道的区别,消息队列的特点如类型、顺序控制以及使用ftok、msgget、msgsnd、msgrcv和msgctl等函数进行创建、发送、接收和管理。最后展示了创建和操作消息队列的示例代码。
摘要由CSDN通过智能技术生成
  • 消息队列是进程之间进行通信的另一种方式。其中无名管道用于两个进程间进行通信;有名管道可用于多个进程间进行通信;消息队列同样用于多进程之间的通信。
  • 特点
    • 消息队列中的消息是有类型和格式的,可以实现随机查询,不一定妖遵循先入先出的顺序,可以按照消息类型读取
    • 读出数据后,数据会被删除
    • 消息队列允许一个或多个进程对其进行写入及读取数据
    • 内核重启或人为删除才会删除消息队列,否则会一直存在于系统中
  • 唯一Key值
    • 系统中可能会同时存在很多消息队列,怎么区分操作的是哪一个呢?通过Key值进行指定。
    • 共享内存、信号、消息队列都需要使用Key值(通过ftok()函数创建)
  • ftok函数
    #include <sys/types.h>
    #include <sys/ipc.h>
    
    key_t ftok(const char * filename, int proj_id);
    功能:获取唯一的Key值
    参数:
        filename:路径名(可以随便设置)
        proj_id:项目ID(1-255(非零整数))
    返回值:
        成功返回Key值,失败返回-1
  • 创建消息队列--msgget函数
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int msgget(key_t key, int msgflag);
    
    功能:
        创建或打开消息队列
        注意:
            以下两种情况,将创建一个新的消息队列
                1、若没有与Key值相同的消息队列,且msgflg标志位包含IPC_CREATE
                2、key参数为IPC_PRIVATE
    参数:
        key:消息队列的id值(ftok函数的返回值)
        msgflag:权限标志位,可以与IPC_CRAETE做或操作(IPC_CREATE|0777),当key命名的消息队列不存在    
                 时,创建一个新的消息队列,若存在,则忽略IPC_CREATE,返回标识符
    返回值:
        成功返回id值,失败返回-1
  • 发送消息--msgsnd函

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    
    作用:将消息发送到消息队列中
    参数:
        msqid:消息队列id
        msgp:待发送消息的缓冲区地址
        msgsz:待发送消息的字节数
        msgflag:IPC_NOWAIT(如果消息队列中的空间不足,则msgsnd的默认行为是阻塞,直到空间变为可用。如        
                 果msgflg设置为IPC_NOWAIT,则调用会失败,并返回错误EAGAIN)
                NULL表示阻塞,直到空间可用
    返回值:
        成功返回0,失败返回-1
  • 接收消息--msgrcv函数

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
    
    功能:
        接受消息队列的消息
    参数:
        msqid:消息队列的id
        msgp:存放接收消息的缓冲区
        msgsz:要接收消息的字节数
        msgtyp:
            type = 0:返回队列中的第一个消息
            type > 0: 返回队列中消息类型为type的第一个消息
            type < 0,返回队列中消息类型值小于或等于type绝对值的消息,如果有多个,则取类型值最小的消息
        
        msgflg:
            0:若消息队列中无消息则一直处于阻塞状态
            IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG
    返回值:
        成功返回接收到的消息长度
        失败返回-1
  • msgctl函数

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    
    功能:主要用于删除消息队列
    参数:
        msqid:消息队列的队列ID
        cmd:
            IPC_RMID:删除消息队列
            
    
        buf:NULL
    返回值:
        成功返回0,失败返回-1
  • msgsnd.c文件

    //msgrcv.c文件
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/msg.h>
    #include <sys/ipc.h>
    
    typedef struct msgBuf{
        long myType;
        char mText[1024];
    }MSGBUF;
    int main(void){
        int msgId, msgSnd, msgRcv, msgCtl;
        MSGBUF rcvBuf;
        MSGBUF sndBuf = {222, "Hello, I'm msgrcv process!\n"};
        //1、生成key值
        key_t key = ftok(".", 1);
        if(key < 0){
            printf("ftok failed!\n");
            exit(-1);
        }
        //2、创建消息队列
        msgId = msgget(key, IPC_CREAT|0777);
        if(msgId < 0){
            printf("msgget failed!\n");
            exit(-1);
        }
        //3、接收消息
        msgRcv = msgrcv(msgId, &rcvBuf, sizeof(rcvBuf.mText), 111, 0);
        if(msgRcv < 0){
            printf("msgrcv failed!\n");
            exit(-1);    
        }
        printf("接收到的消息为: %s\n", rcvBuf.mText);
        //4、发送消息
        msgSnd = msgsnd(msgId, &sndBuf, sizeof(sndBuf.mText), 0);
        if(msgSnd < 0){
            printf("msgsnd failed!\n");
            exit(-1);
        }
        //删除消息队列
        msgctl(msgId, IPC_RMID, NULL);
        if(msgCtl < 0 ){
            printf("msgctl failed!\n");
            exit(-1);    
        }
        
        
        
        return 0;
    }
    
    //msgsnd.c文件
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/msg.h>
    #include <sys/ipc.h>
    
    typedef struct msgBuf{
        long myType;
        char mText[1024];
    }MSGBUF;
    int main(void){
        int msgId, msgSnd, msgRcv, msgCtl;
        MSGBUF rcvBuf;
        MSGBUF sndBuf = {111, "Hello, I'm msgsnd process!\n"};
        //1、生成key值
        key_t key = ftok(".", 1);
        if(key < 0){
            printf("ftok failed!\n");
            exit(-1);
        }
        //2、创建消息队列
        msgId = msgget(key, IPC_CREAT|0777);
        if(msgId < 0){
            printf("msgget failed!\n");
            exit(-1);
        }
        //3、发送消息
        msgSnd = msgsnd(msgId, &sndBuf, sizeof(sndBuf.mText), 0);
        if(msgSnd < 0){
            printf("msgsnd failed!\n");
            exit(-1);
        }
        //接收消息
        msgRcv = msgrcv(msgId, &rcvBuf, sizeof(rcvBuf.mText), 222, 0);
        if(msgRcv < 0){
            printf("msgrcv failed!\n");
            exit(-1);    
        }
        printf("接收到的消息为: %s\n", rcvBuf.mText);
        //删除消息队列
        msgctl(msgId, IPC_RMID, NULL);
        if(msgCtl < 0 ){
            printf("msgctl failed!\n");
            exit(-1);    
        }
        
        
        
        return 0;
    }
    
  • 运行结果

        今天就记录到这里。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值