Message Queues-Unix System-V messages

           
A message queue is a linked list of messages stored within the kernel and identified by a message queue identifier. Generally message queue is called a queue and its identifier a queue ID. There are 2 forms of message queue. One is System V message queue and another one is POSIX message queue. POSIX message queue is newer than System V message queue.
Each message on queue has following attributes:
Β·         long integer type
Β·         length of data portion of message
Β·         data
A message queue allows one or more processes to write messages, which will be read by one or more reading processes.
Sys V Message Queue System calls:
msgget: The function returns the message queue identifier associated to the value of the key argument.
Syntax:          #include <sys/msg.h>
                        int msgget(
                                    key_t key,      //key
                                    int flags);        //creation flags
                        It returns identifier on success or -1 on error.
flag options:
IPC_CREAT – creates queue if it does not already exist.
IPC_EXCL – fail if the file already exists.
msgctl:control message queue
Syntax:          #include <sys/msg.h>
                        int msgctl(
                                    int msqid,       //identifier
                                    int cmd,          //command
                                    struct msqid_ds *data);        //data for a command
                        Returns 0 on success or -1 on error.
Struct msqid_ds – structure for msgctl
                        struct msqid_ds{
                                    struct ipc_perm msg_perm;//permission structure
                                    msgqnum_t msg_qnum;     //no. of messages currently on queue
                                    msglen_t msg_qbytes;        //max. no. of bytes allowed on queue
                                    pid_t msg_lspid;                   //processs ID of last msgsnd
                                    pid_t msg_lrpid;                    //process ID of last msgrcv
                                    time_t msg_stime;                //time of last msgsnd
                                    time_t msg_rtime;                 //time of last msgrcv
                                    time_t msg_ctime;                //time of last msgctl change
                                    };
cmd options:
            IPC_RMID – remove the queue associated with msqid
            IPC_STAT – Fill the structure pointed to by data with information about the queue.
            IPC_SET – Set four properties of the queue
                                    msg_perm.uid
                                    msg_perm.gid
                                    msg_perm.mode
                                    msg_qbytes
msgsnd: To send or receive a message, the calling process allocates a structure of a     message.
Syntax:          #include sys/msg.h>
                        int msgsnd(
                                    int msqid,                   //identifier
                                    const void *msgp,     //message
                                    size_t msgsize,         //size of message
                                    int flags);                    //flags
                        Returns 0 on success or -1 on error.
msgrcv: To send or receive a message, the calling process allocates a structure of a message.
Syntax:          #include sys/msg.h>
                        int msgrcv(
                                    int msqid,                   //identifier
                                     void *msgp,              //message
                                    size_t mtextsize,       //size of mtext buffer
                                    long msgtype,           //message type requested
                                    int flags);                    //flags
                        Returns no. of bytes placed in mtext on success or -1 on error.
Struct msg – structure for msgsnd and msgrcv
                        struct msg{
                                    long mtype;                           //message type
                                    char mtext[MTEXTSIZE];    //message text
                                    };
flag options:
      IPC_NOWAIT – for immediate return if no message of the requested type is on the queue.
           MSG_EXCEPT – used with msgtype greterthan 0 to read the first message on the queue with message type that differs from msgtype.
            MSG_NOERROR – to truncate the message text if no longer than mtextsize.
Message passing has evolved through following stages:
Pipes:
Pipes were the first widely used form of IPC, available both within programs and shell. The problem with is that they are usable only between processes that have common ancestor i.e., parent-child relation. This problem was fixed with the introduction of named pipes i.e., FIFOs
Limits of System V Message Queue:
       Limit on the total size of all messages in a queue.
       Limit on the number of messages in a queue.
       Limit on the size of a message
       Limit on the number of queues.
Unix Kernel Support for Messages:
Kernel executes different processes and supports IPC. The message queue lifetime is same as kernel, it is destroyed when the system is reboot. A process can invoke msgsnd() to send a message. He needs to pass the IPC identifier of the receiving message queue, the size of the message and a message structure, including the message type and text.
On the other side, a process invokes msgrcv() to receive a message, passing the IPC identifier of the message queue, where the message should get stored, the size and a value t.
t specifies the message returned from the queue, a positive value means the first message with its type equal to t is returned, a negative value returns the last message equal to type t and zero returns the first message of the queue.
Those functions are defined in include/linux/msg.h and implemented in ipc/msg.c
There are limitations upon the size of a message (max), the total number of messages (mni) and the total size of all messages in the queue (mnb).
Unix APIs [Application Programming Interface] for Messages:
           
POSIX message queue system calls:
            mq_open – open msg queue
            mq_close – close msg queue
            mq_unlink – remove msg queue
            mq_send – send msg
            mq_receive – receive msg
            mq_timedsend – send msg with timeout
            mq_timedreceive – receive msg with timeout
            mq_notify – register or unregister for msg notification
            mq_getattr – get msg queue attributes
            mq_setattr – set msg queue attributes
System V message queue system calls:
            msgget – get msg queue identifier
            msgctl – control msg queue
            msgsnd – send msg
            msgrcv – receive msg
Client/Server Example:
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
int main (void) {
        key_t ipckey;
        int mq_id;
        struct { long type; char text[100]; } mymsg;
        /* Generate the ipc key */
        ipckey = ftok(“/tmp/foo”, 42);
        printf(“My key is %dn”, ipckey);
        /* Set up the message queue */
        mq_id = msgget(ipckey, IPC_CREAT | 0666);
        printf(“Message identifier is %dn”, mq_id);
        /* Send a message */
        memset(mymsg.text, 0, 100); /* Clear out the space */
        strcpy(mymsg.text, “Hello, world!”);
        mymsg.type = 1;
        msgsnd(mq_id, &mymsg, sizeof(mymsg), 0);
}
Client :- Code to retrieve a message from a queue
 
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
 
int main (void) {
 
        key_t ipckey;
        int mq_id;
        struct { long type; char text[100]; } mymsg;
        int received;
 
        /* Generate the ipc key */
        ipckey = ftok("/tmp/foo", 42);
        printf("My key is %dn", ipckey);
 
        /* Set up the message queue */
        mq_id = msgget(ipckey, 0);
        printf("Message identifier is %dn", mq_id);
 
        received = msgrcv(mq_id, &mymsg, sizeof(mymsg), 0, 0);
 
        printf("%s (%d)n", mymsg.text, received);
}
Output of the client and server code:
 
sunbox$ ./mq_server
My key is 704654099
Message identifier is 2
sunbox$ ./mq_client
My key is 704654099
Message identifier is 2
Hello, world! (104)

Leave a Reply

Your email address will not be published. Required fields are marked *

Enable Notifications OK No thanks