1. What is a message queue
Message queuing provides a way to send a data block from one process to another.Each data block is considered to contain a type, and the receiving process can independently receive different types of data structures. We can avoid the synchronization and blocking of named pipes by sending messages. However, message queues, like named pipes, have a maximum length limit for each data block.
Linux uses macros MSGMAX and MSGMNB to limit the maximum length of a message and a queue.
2. Using Message Queuing on Linux
Linux provides a series of function interfaces for message queues that allow us to easily use for interprocess communication. It is used similarly to the other two System V PIC mechanisms, semaphores and shared memory.
1. msgget function
This function is used to create and access a message queue. Its prototype is:
int msgctl(int msgid, int command, struct msgid_ds *buf);
command is the action to be taken, which can take three values.
IPC_STAT: Set the data in the msgid_ds structure to the current associated value of the message queue, that is, overwrite the value of msgid_ds with the current associated value of the message queue.
IPC_SET: If the process has sufficient privileges, set the current associated value of the message queue to the value given in the msgid_ds structure
IPC_RMID: Delete message queue
buf is a pointer to the msgid_ds structure, which points to the message queue mode and the structure of access rights. The msgid_ds structure includes at least the following members:
struct msgid_ds { uid_t shm_perm.uid; uid_t shm_perm.gid; mode_t shm_perm.mode; };
3. Use Message Queuing for Interprocess Communication
Here we will write two programs, msgreceive and msgsned, to represent receiving and sending information. Normally, we allow both programs to create messages, but only after the recipient has received the last message, does it delete it.
The source code for the program that receives the information is msgreceive.c:
/*Communicate using Message Queuing*/ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> struct msg_st { long int msg_type; char text[BUFSIZ]; }; int main() { int running = 1; int msgid = -1; struct msg_st data; long int msgtype = 0; //Note 1//Create Message Queue msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //Get messages from the queue until an end message is encountered while(running) { if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("You wrote: %s\n",data.text); //end Encountered if(strncmp(data.text, "end", 3) == 0) running = 0; } //Delete message queue if(msgctl(msgid, IPC_RMID, 0) == -1) { fprintf(stderr, "msgctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
The source code for the program that sent the message, msgsend.c, is:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.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 running = 1; struct msg_st data; char buffer[BUFSIZ]; int msgid = -1; //Create message queue msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //Write a message to the message queue until the end is written while(running) { //Input data printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); data.msg_type = 1; //Note 2 strcpy(data.text, buffer); //Send data to queue if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } //Enter end to end input if(strncmp(buffer, "end", 3) == 0) running = 0; sleep(1); } exit(EXIT_SUCCESS); }
4. Comparison of message queues and named pipes
Message queues have many similarities with named pipes. Like named pipes, processes that communicate with message queues can be unrelated processes, and they all transmit data by sending and receiving. In named pipes, data is sent in write, data is received in read, and data is sent in msgsnd, and data is received in message queuesReceive data using msgrcv. They also have a maximum length limit for each data.
The advantages of message queues over named pipes are that 1. Message queues can also exist independently of sending and receiving processes, eliminating the difficulties that may arise when synchronizing named pipes open and close. 2. Sending messages also avoids synchronization and blocking problems with named pipes, and does not require the process to provide its own synchronization methods.3, the receiver can selectively receive data through the message type, rather than by default, as in a named pipe.