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

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 
#include 
#include 
#include 

#include 
#include 
#include 

#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  \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 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    #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;
    }
    
    

你可能感兴趣的:(C语言,linux操作系统,c++,c语言)