POSIX Message Queue

Posted by alkhatareykha on Mon, 22 Jul 2019 21:42:49 +0200

 

1. What is the message queue?

(1) Message queuing is an IPC method.

(2) Stored in the kernel and mounted under/dev/mqeue using VFS.

(3) Data structure: queues with priority

 

2. Comparison of Message Queuing and Management

(1) Pipelines are analogous to phone calls and message queues are analogous to mail.

(2) For pipeline communication, both the sender and the receiver must open the pipeline, otherwise the communication will fail or be meaningless.

If the pipe is closed, the data in the pipe will be lost.

(3) Message queues, which can be read and written at different times by sender and receiver.

If the message queue structure is closed, the data remains in the message queue file.

 

3. Comparison of POSIX and SystemV message queues

POSIX updates are simpler and more powerful.

(1) Reading the Posix message queue always returns the earliest message with the highest priority, while reading the System V message queue returns messages with any given priority.

(2) When a message is placed in an empty queue, the Posix message queue allows a signal to be generated or a thread to be started, while the System V message queue does not provide a similar mechanism.

 

4.api learning

(0) Link POSIX message queues using -lrt

(1) Create a message queue file

Use API:

       mqd_t mq_open(const char *name, int oflag);
       mqd_t mq_open(const char *name, int oflag, mode_t mode,
                     struct mq_attr *attr);
void creat_mq(const char *mq_name)
{
    int oflag;
    mode_t mode;
    mqd_t mqd = -1;

    oflag = O_RDWR | O_CREAT | O_EXCL;
    mode = S_IRUSR | S_IWUSR | S_IRGRP  | S_IROTH ;

    mqd = mq_open(mq_name, oflag, mode, NULL);    // Created mq stay/dev/mqueue lower
    if (mqd == -1) {
        perror("mq_open");
        goto __end;
    }

__end:
    if (!mqd) {
        printf("mq_close");
        mq_close(mqd);
    }
}

(3) Delete message queue files

Use API

int mq_unlink(const char *name);
void unlink_mq(const char *mq_name)
{
    if (mq_unlink(mq_name) < 0) 
        perror("mq_unlink");
}

(4) Setting message queue properties

       int mq_getattr(mqd_t mqdes, struct mq_attr *attr);

       int mq_setattr(mqd_t mqdes, const struct mq_attr *newattr,
                        struct mq_attr *oldattr);

Related attributes:

           struct mq_attr {
               long mq_flags;       /* Flags: 0 or O_NONBLOCK */
               long mq_maxmsg;      /* Max. number of messages on queue */
               long mq_msgsize;     /* Max. message size (bytes) */
               long mq_curmsgs;     /* # of messages currently in queue */
           };

(5) Send and receive messages

Use API

      int mq_send(mqd_t mqdes, const char *msg_ptr,
                     size_t msg_len, unsigned int msg_prio);
     ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
                          size_t msg_len, unsigned int *msg_prio);
mqd_t open_mq(const char *name, int oflag)
{
    mqd_t mqd = -1;

    mqd = mq_open(name, O_RDWR);
    if (mqd < 0) 
        perror("mq_open");

    return mqd;
}

int send_mq(mqd_t mqd, const char *buf, int len, int priority)
{
    int n;

    n = mq_send(mqd, buf, len , priority);
    if (n < 0 || n != len) {
        perror("mq_send");
    }

    return n;
}

int recv_mq(mqd_t mqd, char *buf)
{
    int n;
    struct mq_attr attr;

    if (mq_getattr(mqd, &attr) < 0) 
        perror("mq_getattr");
    n = mq_receive(mqd, buf, attr.mq_msgsize, NULL);    // Need to use msg_len
    if (n < 0 || n != attr.mq_msgsize) 
        perror("mq_receive");

    return n;
}

void test_send_recv()
{
    const char *mq_file = MQ_FILE;
    char buf[100];
    mqd_t mqd = -1;
    int send_number, recv_number, nbytes, priority;

    if ((mqd = open_mq(mq_file, O_RDWR)) < 0)
        goto __end;
    snprintf(buf, sizeof(buf), "hello world\n");
    send_number = 3;
    priority = 20;
    while (send_number--) 
        nbytes = send_mq(mqd, buf, strlen(buf), priority);

    bzero(buf, sizeof(buf));
    recv_number = 4;                // Default Blocked Read
    while (recv_number--) {        
        recv_mq(mqd, buf);
        printf("recv : %s\n", buf);
    }

__end:
    if (mqd != -1)
        close(mqd);
}

It is important to note that when MSG is accepted, the msg_len used is obtained from the MSG file, which is mqd_attr.mq_msgsize.

Topics: PHP