System V消息队列(2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Alatebloomer/article/details/81901564

消息发送/接收API

msgsnd函数

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

参数

   msgid: 由msgget函数返回的消息队列标识码, 也可以是通过ipcs命令查询出来的一个已经存在的消息队列的ID号

   msgp:是一个指针,指针指向准备发送的消息,

   msgsz:是msgp指向的消息长度, 注意:这个长度不含保存消息类型的那个long int长整型

   msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情,如果msgflg = IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。

消息结构在两方面受到制约: (1)它必须小于系统规定的上限值(MSGMAX); (2)它必须以一个long int长整数开始,接收者函数将利用这个长整数确定消息的类型;

//消息结构参考形式如下:
struct msgbuf
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1];    /* message data, 可以设定为更多的字节数 */
};
#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[0]);
        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;
    ptr = (struct msgbuf*)malloc(sizeof(long) + len);
    ptr->mtype = type;

/*
    if (msgsnd(msgid, ptr, len, IPC_NOWAIT) < 0)//非阻塞
        ERR_EXIT("msgsnd");
*/
    if (msgsnd(msgid, ptr, len, 0) < 0)//阻塞
        ERR_EXIT("msgsnd");



    return 0;
}

msgrcv函数

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

参数

   msgid: 由msgget函数返回的消息队列标识码

   msgp:是一个指针,指针指向准备接收的消息;

   msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型

   msgtype:它可以实现接收优先级的简单形式(见下图)

   msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事(见下图)

返回值:

   成功->返回实际放到接收缓冲区里去的字节数(注意: 此处并不包含msgbuf中的mtype的长度);

   失败->返回-1;

msgtyp参数

msgtyp=0

返回队列第一条信息

msgtyp>0

返回队列第一条类型等于msgtype的消息

msgtyp<0

返回队列第一条类型小于等于(<=)msgtype绝对值的消息,并且是满足条件的消息类型最小的消息(按照类型进行排序的顺序进行接收消息)

msgflg参数

msgflg=IPC_NOWAIT

队列没有可读消息不等待,返回ENOMSG错误。

msgflg=MSG_NOERROR

消息大小超过msgsz(msgrcv 函数的第三个参数)时被截断, 并且不会报错

msgtyp>0且msgflg=MSG_EXCEPT

接收类型不等于msgtype的第一条消息

#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 */
};

#define MSGMAX 8192
int main(int argc, char *argv[])
{
    int flag = 0;
    int type = 0;
    int opt;

    while (1)
    {
        opt = getopt(argc, argv, "nt:");
        if (opt == '?')
            exit(EXIT_FAILURE);

        if (opt == -1)
            break;

        switch (opt)
        {
        case 'n':
            /*printf("AAAA\n");*/
            flag |= IPC_NOWAIT;
            break;
        case 't':
            /*
            printf("BBBB\n");
            int n = atoi(optarg);
            printf("n=%d\n", n);
            */
            type = atoi(optarg);
            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;
    int n = 0;
    if ((n = msgrcv(msgid, ptr, MSGMAX, type, flag)) < 0)
        ERR_EXIT("msgsnd");

    printf("read %d bytes type=%ld\n", n, ptr->mtype);

    return 0;
}

getopt用法是解析命令行参数

#include <unistd.h>
int getopt(int argc, char * const argv[],
                  const char *optstring);
 
extern char *optarg;
extern int optind, opterr, optopt;


//示例: 解析 ./main -n -t 3 中的参数选项
//t后面的:表示t后面可以跟参数 参数保存在optarg中
int main(int argc, char *argv[])
{
    while (true)
    {
        int opt = getopt(argc, argv, "nt:");
        if (opt == '?')
            exit(EXIT_FAILURE);
        else if (opt == -1)
            break;
 
        switch (opt)
        {
        case 'n':
            cout << "-n" << endl;
            break;
        case 't':
            int n = atoi(optarg);
            cout << "-t " << n << endl;
            break;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Alatebloomer/article/details/81901564