Table of Contents
Message queues are an essential form of Inter-Process Communication (IPC) used in various applications, such as task scheduling, buffering data between processes or threads, and managing requests in web servers. This article will explore POSIX queues, a type of message queue provided by the POSIX standard, and walk you through the process of using them in C programming with a practical example.
What Are Queues?
A queue is a linear data structure that stores a collection of elements. In a queue, elements are added (enqueued) to the rear and removed (dequeued) from the front following a First-In-First-Out (FIFO) order. Queues are commonly used to manage tasks in a sequential manner, simulating real-world scenarios like waiting in line.
This article explains queues and their implementation in C.
Introduction to POSIX Queues
POSIX queues, also known as message queues, enable separate processes to send and receive messages in a synchronized manner. Messages are stored in a queue and retrieved following the FIFO order. POSIX queues are useful for synchronizing communication between different processes in an efficient manner.
Key Functions for Working with POSIX Queues
To work with POSIX queues, you’ll need to familiarize yourself with the following functions:
mq_open()
: Opens or creates a message queue.mq_close()
: Closes a message queue.mq_unlink()
: Removes a message queue.mq_send()
: Sends a message to the queue.mq_receive()
: Receives a message from the queue.
Syntax and Parameters
Here’s a brief explanation of the syntax and parameters for each function:
mq_open()
:mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
name
: The name of the message queue.oflag
: The flags for opening the queue (e.g.,O_CREAT
,O_WRONLY
,O_RDONLY
).mode
: The permissions for the queue.attr
: A pointer to amq_attr
structure that specifies the queue’s attributes.
mq_close()
:int mq_close(mqd_t mqdes);
mqdes
: The message queue descriptor.
mq_unlink()
:int mq_unlink(const char *name);
name
: The name of the message queue.
mq_send()
:int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
mqdes
: The message queue descriptor.msg_ptr
: A pointer to the message to be sent.msg_len
: The length of the message.msg_prio
: The message priority.
mq_receive()
:ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
mqdes
: The message queue descriptor.msg_ptr
: A pointer to the buffer where the received message will be stored.msg_len
: The length of the buffer.msg_prio
: A pointer to the variable where the message priority will be stored.
Example: Using POSIX Queues for Inter-Process Communication
The following example demonstrates the usage of POSIX queues for communication between two processes: a sender and a receiver. We’ll provide separate code snippets for each process and explain the code using comments.
Sender Process
#include <fcntl.h> #include <mqueue.h> #include <stdio.h> #include <stdlib.h> #include <string.h int main() { mqd_t mq; struct mq_attr attr; char buffer[1024]; // Initialize the queue attributes attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = 1024; attr.mq_curmsgs = 0; // Open or create the message queue mq = mq_open("/my_queue", O_CREAT | O_WRONLY, 0644, &attr); if (mq == -1) { perror("mq_open"); exit(1); } // Send a message to the queue strcpy(buffer, "Hello, world!"); if (mq_send(mq, buffer, strlen(buffer), 0) == -1) { perror("mq_send"); exit(1); } // Close the message queue if (mq_close(mq) == -1) { perror("mq_close"); exit(1); } return 0; }
Receiver Process
#include <fcntl.h> #include <mqueue.h> #include <stdio.h> #include <stdlib.h> int main() { mqd_t mq; char buffer[1024]; // Open the message queue mq = mq_open("/my_queue", O_RDONLY); if (mq == -1) { perror("mq_open"); exit(1); } // Receive a message from the queue if (mq_receive(mq, buffer, 1024, NULL) == -1) { perror("mq_receive"); exit(1); } printf("Received: %s\n", buffer); // Close the message queue if (mq_close(mq) == -1) { perror("mq_close"); exit(1); } // Remove the message queue if (mq_unlink("/my_queue") == -1) { perror("mq_unlink"); exit(1); } return 0; }
Compiling and Running the Code
To compile and run the code, follow these steps:
- Save the sender process code in a file named
sender.c
and the receiver process code in a file namedreceiver.c
. - Compile both files using the following commands:
gcc -o sender sender.c -lrt gcc -o receiver receiver.c -lrt
- Run the sender and receiver processes separately in two different terminal windows:
./sender
./receiver
The receiver process should output the message sent by the sender process: “Hello, world!”.
In conclusion, POSIX queues provide a powerful and efficient way to facilitate communication between different processes in C programming. By understanding the syntax and parameters of key functions and following the provided example, you can easily implement and use POSIX queues in your own projects.
Hi, I’m Vivek, a Senior Embedded Innovation Specialist. I have been working on Embedded Systems and IoT for the past 11 years. I love to share my knowledge and train those who are interested. Nerdyelectronics.com was started out of this interest. You can read my full profile in this link.