Linux message queuing

Basic concepts

  a message queue is a linked list that stores messages with specific formats and priorities.
  processes with write permission to the message queue can add new messages to it, and processes with read permission to the message queue can read messages from it.
   the message queue continues with the kernel. The message queue will not be deleted until the kernel is restarted or a message queue is deleted.
  there are three operations on message queue:

  1. Open or create a message queue.
  2. Read and write operations.
  3. Gets or sets the message queue properties.

ftok

   the kernel persistence of message queues requires that each message queue must have a corresponding unique key value in the system. You can use ftok to obtain the key value:

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok ( char *pathname, char proj ); /* f It's file and k is key */

pathname is the file name; proj is the project name, not 0.

msgget

   use msgget to create a message queue. The function returns the message queue descriptor corresponding to the key value:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget ( key_t key, int msgflg );
  • Key is the key value, which is obtained by ftok
  • msgflg is the flag bit. There are the following options. These options can be or operated:
  1. IPC_CREAT: create a new message queue.
  2. IPC_EXCL: with IPC_ Used together with creat, it means that if the message queue to be created already exists, an error is returned.
  3. IPC_NOWAIT: msgsnd and msgrcv are not blocked when the message queue cannot meet the read and write requirements.

message format

  in the message queue, the format of each message is struct msgbuf:

struct msgbuf {
    long mtype;    // Message type
    char mtext[1]; // First address of message data
};

msgsnd

   the function of msgsnd is to send a message to the message queue. If the message is sent successfully, it will return 0, otherwise it will return - 1:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg );
  • msqid: open message queue id.
  • msgp: structure for storing messages.
  • msgsz: message data length.
  • msgflg: send flag, commonly used 0 and IPC_NOWAIT.
  1. If msgflg is 0, msgsnd will be blocked when the message queue does not have enough space to send messages.
  2. If msgflg is IPC_NOWAIT, msgsnd will not be blocked when the message queue does not have enough space to hold the message to be sent.

msgrcv

  msgrcv reads a message of type msgtyp from the message queue msqid. The message length is msgsz, and stores the message in the msgbuf structure pointed to by msgp:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg );

After successfully reading a message, the message in the message queue will be deleted.
   msgtype can realize a simple receive priority:

  1. If msgtype is 0, get the first message in the queue.
  2. If msgtype is greater than zero, get the first message with the same message type.
  3. If msgtype is less than zero, get the first message whose type is equal to or less than the absolute value of msgtype.

   msgflg has the following options, which can be or operated:

  • 0: ignore msgflg.
  • IPC_NOWAIT: if there is no message that meets the condition, the function returns immediately.
  • IPC_ Excel: used with msgtyp > 0 to return the first message in the message queue whose type is not msgtyp.
  • IPC_NOERROR: if the qualified message content in the message queue is greater than the requested msgsz bytes, the message will be truncated and the truncated part will be lost.

msgctl

  msgctl performs cmd operation on message queue msqid:

int msgctl ( int msqid, int cmd, struct msqid_ds *buf );

There are three types of cmd operations:

  • IPC_STAT: used to obtain the properties of the message queue. The returned properties are stored in the msqid structure pointed to by buf.
  • IPC_SET: used to set the properties of the message queue. The properties to be set are stored in the msqid structure pointed to by buf.
  • IPC_RMID: deleted message queue msqid.

If the function is executed successfully, it returns 0; otherwise, it returns - 1.

Operation message queue

  msgreceive.c is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>

struct msg_st {
    long int msg_type;
    char text[BUFSIZ];
};

int main ( int argc, char **argv ) {
    int msgid = -1;
    struct msg_st data;
    long int msgtype = 0;
    msgid = msgget ( ( key_t ) 1234, 0666 | IPC_CREAT );

    if ( msgid == -1 ) {
        fprintf ( stderr, "msgget failed width error: %d\n", errno );
        exit ( EXIT_FAILURE );
    }

    while ( 1 ) { /* Get the message from the queue until 'end' is encountered */
        if ( msgrcv ( msgid, ( void * ) &data, BUFSIZ, msgtype, 0 ) == -1 ) {
            fprintf ( stderr, "msgrcv failed width erro: %d", errno );
        }

        printf ( "You wrote: %s", data.text );

        if ( strncmp ( data.text, "end", 3 ) == 0 ) {
            break;
        }
    }

    if ( msgctl ( msgid, IPC_RMID, 0 ) == -1 ) { /* Delete message queue */
        fprintf ( stderr, "msgctl(IPC_RMID) failed\n" );
    }

    exit ( EXIT_SUCCESS );
}

  msgsend.c is as follows:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <errno.h>

#define MAX_TEXT 512

struct msg_st {
    long int msg_type;
    char text[MAX_TEXT];
};

int main ( int argc, char **argv ) {
    struct msg_st data;
    char buffer[BUFSIZ];
    int msgid = -1;
    msgid = msgget ( ( key_t ) 1234, 0666 | IPC_CREAT );

    if ( msgid == -1 ) {
        fprintf ( stderr, "msgget failed error: %d\n", errno );
        exit ( EXIT_FAILURE );
    }

    while ( 1 ) {
        printf ( "Enter some text: \n" );
        fgets ( buffer, BUFSIZ, stdin );
        data.msg_type = 1;
        strcpy ( data.text, buffer );

        if ( msgsnd ( msgid, ( void * ) &data, MAX_TEXT, 0 ) == -1 ) {
            fprintf ( stderr, "msgsnd failed\n" );
            exit ( EXIT_FAILURE );
        }

        if ( strncmp ( buffer, "end", 3 ) == 0 ) {
            break;
        }

        sleep ( 1 );
    }

    exit ( EXIT_SUCCESS );
}

Tags: Linux

Posted on Tue, 05 Oct 2021 16:58:59 -0400 by OmarHaydoor