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)