system v消息队列:msgsnd函数 ,msgrcv函数

文章详细介绍了SystemVIPC中的msgsnd函数和msgrcv函数,用于在消息队列中发送和接收消息。msgsnd函数用于将消息添加到消息队列,参数包括消息队列ID、消息指针、消息长度和标志,如IPC_NOWAIT。msgrcv函数则用于从消息队列接收消息,可以设置不同的标志处理无消息的情况,如IPC_NOWAIT。文章提供了函数使用示例并解释了消息结构和相关参数的含义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.msgsnd函数

功能:把一条消息添加到消息队列中

原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

参数:
msgid:由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备发送的消息;至少2个参数:消息类型以及实际数据存放的场所;
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgflg:控制着当前消息队列满或达到系统上限时将要发生的事情

返回值:成功返回0;失败返回-1

        msgflg=IPC_NOWAIT表示队列满不等待,返回EAGAIN错误;0:表示以阻塞的方式发送
消息结构在2方面受到制约。
(1)首先,他必须小于系统规定的上限值MSGMAX
(2)其次,他必须以一个long int长整型开始,接收者函数利用这个长整型确定消息的类型
消息结构参考如下:


struct msgbuf 
{
    long mtype;       /* message type, must be > 0 *///消息类型
    char mtext[1];    /* message data *///存放消息的场所
};

示例:

//
// Created by wangji on 19-8-12.
//

// p25 system v消息队列(二)

#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m) \
        do \
        { \
             perror(m); \
             exit(EXIT_FAILURE);    \
        } while (0);

struct msgbuf 
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1];    /* message data */
};



int main(int argc, char** argv)
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <bytes> <type>\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    int len = atoi(argv[1]);//消息长度
    int type = atoi(argv[2]);//消息类型
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
    {
        ERR_EXIT("msgget");
    }

    //准备一个消息,分配内存
    struct msgbuf *ptr;

    //消息内存大小=消息类型long mtype+发送的消息的长度len
    ptr = (struct msgbuf*) malloc(sizeof(long) + len);
    ptr->mtype = type;
    if (msgsnd(msgid, ptr, len, 0) < 0)//0表示消息队列满的时候,以阻塞的方式发送
    {
        ERR_EXIT("msgsnd");
    }
    
    /*
    if (msgsnd(msgid, ptr, len, IPC_NOWAIT) < 0)//IPC_NOWAIT表示非阻塞,当发送的消息超过msgmnb时
    {
        ERR_EXIT("msgsnd");
    }
    //会返回EAGAIN 错误:Resource temporarily unavailable
    //发送的消息不会阻塞了
    */



    return 0;
}

2.msgrcv函数

功能:是从一个消息队列接收消息

原型;ssize_t msgrcv(int msgid, void *msgp, size_t msgsz, long msgtype,
                      int msgflg);

参数:
msgid:由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备接收的消息
msgsz:由msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgtype:它可以实现接收优先级的简单形式
msgflg:控制着队列中没有相应类型的消息可供接收时,将要发生的事情
msgflag:
若消息队列中没有消息,msgflag=IPC_NOWAIT,那么会返回EAGAIN
若消息队列中没有消息,msgflag=0,那么消息队列中的消息会阻塞

返回值
成功返回实际放到接收缓冲区里去的字符个数;
失败,返回-1
  • 对于msgtype和msgflag的解释
    msgtype=0返回队列第一条消息
    msgtype>0返回队列第一条类型等于msgtype的消息
    msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息
    msgflag=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误
    msgflag=IPC_NOERROR,消息大小超过msgsz时被截断
    msgtype>0且msgflg=MSC_EXCEPT,接收类型不等于msgtype的第1条消息
    

    示例

    //
    // Created by wangji on 19-8-12.
    //
    
    // p25 system v消息队列(二)
    
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    
    #define ERR_EXIT(m) \
            do \
            { \
                 perror(m); \
                 exit(EXIT_FAILURE);    \
            } while (0);
    
    //一条消息的最大值不能超过8192
    #define MSGMAX 8192
    
    struct msgbuf 
    {
        long mtype;       /* message type, must be > 0 */
        char mtext[1];    /* message data */
    };
    
    
    int main(int argc, char** argv)
    {
        int flag = 0;
        int type = 0;
        int opt;
    
        while (1)
        {
            //man 3 getopt查询该函数用法
            //因为执行的时候:./P26msg_recv -n -t 1(等价于./P26msg_recv -n -t1),可以用getopt函数来解析参数
            //-n表示消息以非阻塞方式接收(n),,-t 1表示消息类型为1(t:),可以用:"nt:"来表示,:表示-t 参数后面的1
            opt = getopt(argc, argv, "nt:");
            if (opt == '?')//表示解析到不认识的参数
            {
                exit(EXIT_FAILURE);
            }
            if (opt == -1)//opt=-1,表示所有的参数都解析完毕
            {
                break;
            }
    
            //switch解析参数
            switch (opt)
            {
                case 'n':
                    // printf("AAA\n");
                    flag |= IPC_NOWAIT;
        
                    break;
                case 't':
                    // printf("BBB\n");
                    type = atoi(optarg);//t后面的参数1保存在optarg
                    //printf("n=%d\n",type);//type=0表示按顺序接收            
                    break;
            }
        }
    
    
        int msgid;
        msgid = msgget(1234, 0);
        if (msgid == -1)
        {
            ERR_EXIT("msgget");
        }
    
        struct msgbuf *ptr;
        ptr = (struct msgbuf*) malloc(sizeof(long) + MSGMAX);//实际消息的最大值
        //ptr->mtype = type;
        //msgrcv( msqid, &buf1, recvlength ,3,0 ) ;
        int n;//接收到的字节数
        if ((n = msgrcv(msgid, ptr, MSGMAX, type, flag)) < 0)
        {
            ERR_EXIT("msgsnd");
        }
        printf("type=%d, bytes=%d\n", ptr->mtype, (int)n) ;
        return 0;
    }
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值