ADVERTISEMENT
Responsive Ad Unit • Systems Architecture & Low-Level Engineering

POSIX Message Queues

POSIX Message Queues provide reliable message-based communication between unrelated processes. Unlike pipes, which operate as byte streams, POSIX message queues preserve message boundaries and support message priorities, making them suitable for real-time and event-driven applications.

Learning Objectives

  • Understand POSIX Message Queues.
  • Learn queue creation and naming.
  • Study queue descriptors.
  • Understand message priorities.
  • Learn queue attributes.
  • Prepare for sending and receiving messages.

1. What is a POSIX Message Queue?

A POSIX message queue is a kernel-managed IPC object that stores complete messages. Each message is delivered exactly as it was sent, without losing its boundaries. Multiple processes can open the same queue by using its name.

2. Why Use Message Queues?

Requirement How Message Queues Help
Preserve Messages Messages remain intact.
Priority Processing Higher priority messages are delivered first.
Multiple Processes Supports unrelated processes.
Reliable Communication Kernel manages queue storage.
Real-Time Systems Designed for deterministic communication.

3. POSIX Message Queue Architecture

Producer ↓ mq_send() ↓ Kernel Message Queue ↓ mq_receive() ↓ Consumer

The kernel stores messages inside the queue until they are received or the queue reaches its configured capacity.

4. Queue Names

POSIX message queues are identified using names. Queue names normally begin with a forward slash.

"/orders" "/events" "/sensor_queue"

Processes using the same queue must specify the identical name.

5. Queue Descriptor (mqd_t)

After successfully opening a queue, the kernel returns a message queue descriptor of type mqd_t. Applications use this descriptor in all subsequent queue operations.

mqd_t mq;

6. Queue Attributes

Each queue maintains operational attributes represented by the struct mq_attr structure.

struct mq_attr { long mq_flags; long mq_maxmsg; long mq_msgsize; long mq_curmsgs; };

7. Queue Attribute Fields

Field Description
mq_flags Queue behavior (blocking/non-blocking).
mq_maxmsg Maximum number of messages.
mq_msgsize Maximum size of one message.
mq_curmsgs Current number of queued messages.

8. Linux Implementation

Linux commonly exposes POSIX message queues through the mqueue virtual filesystem. When mounted, queue objects are visible under:

/dev/mqueue

The objects are managed by the kernel rather than being ordinary files.

9. Advantages

  • Messages retain their boundaries.
  • Supports message priorities.
  • Kernel-managed buffering.
  • Suitable for real-time applications.
  • Supports unrelated processes.

10. Interview Questions

  1. What is a POSIX message queue?
  2. How does it differ from a pipe?
  3. Why are message boundaries important?
  4. What type represents a message queue descriptor?
  5. What information does struct mq_attr contain?
  6. What is the purpose of mq_maxmsg?
  7. What is stored in mq_curmsgs?
  8. Where are POSIX message queues commonly exposed on Linux?
  9. Why are message priorities useful?
  10. Which applications commonly use message queues?

11. mq_open()

The mq_open() function creates a new POSIX message queue or opens an existing one.

#include <mqueue.h> #include <fcntl.h> mqd_t mq_open(const char *name, int oflag, ...);

When creating a new queue, additional arguments specify the permission mode and queue attributes.

12. mq_open() Parameters

Parameter Description
name Name of the message queue.
oflag Creation and access flags.
mode Permission bits (used with O_CREAT).
attr Pointer to struct mq_attr.

13. Queue Creation Flags

Flag Description
O_RDONLY Open for receiving only.
O_WRONLY Open for sending only.
O_RDWR Open for both sending and receiving.
O_CREAT Create queue if it does not exist.
O_EXCL Fail if queue already exists.
O_NONBLOCK Enable non-blocking operations.

14. O_CREAT

When O_CREAT is specified, the kernel creates the message queue if it does not already exist. If the queue exists and O_EXCL is not specified, mq_open() returns a descriptor for the existing queue.

mq_open("/orders", O_CREAT | O_RDWR, 0666, NULL);

15. O_EXCL

The O_EXCL flag is meaningful only when combined with O_CREAT. If the named queue already exists, the call fails with an error rather than opening the existing queue.

mq_open("/orders", O_CREAT | O_EXCL | O_RDWR, 0666, NULL);

16. Queue Permission Bits

POSIX message queues use UNIX-style permission bits.

Permission Description
0400 Owner Read
0200 Owner Write
0040 Group Read
0020 Group Write
0004 Others Read
0002 Others Write

17. Queue Creation Workflow

Application ↓ mq_open() ↓ Kernel Checks Queue Name ↓ Queue Exists? ↓ Yes → Return Descriptor ↓ No ↓ O_CREAT? ↓ Yes ↓ Kernel Creates Queue ↓ Return mqd_t

18. Example: Creating a Queue

#include #include int main(void) { mqd_t mq; mq = mq_open("/sensor", O_CREAT | O_RDWR, 0666, NULL); if (mq == (mqd_t)-1) return 1; mq_close(mq); return 0; }

19. Linux Commands

Command Description
ls /dev/mqueue Display existing message queues.
mount | grep mqueue Verify that the mqueue filesystem is mounted.
cat /proc/sys/fs/mqueue/msg_max Maximum number of messages per queue.
cat /proc/sys/fs/mqueue/msgsize_max Maximum message size.
man mq_open Message queue API documentation.

20. Interview Questions

  1. What is the purpose of mq_open()?
  2. When are the mode and attr arguments required?
  3. What happens if O_CREAT is omitted?
  4. How does O_EXCL work?
  5. Which type is returned by mq_open()?
  6. What does O_NONBLOCK change?
  7. What happens if the queue already exists?
  8. Where are message queues commonly visible on Linux?
  9. How are permissions assigned to a new queue?
  10. Which Linux file shows the maximum message size?

21. mq_send()

The mq_send() function places a message into a POSIX message queue. Each message remains intact and is assigned a priority.

#include <mqueue.h> int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);

22. mq_receive()

The mq_receive() function removes the highest-priority message currently available from the queue.

#include <mqueue.h> ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

23. Message Priorities

Every message sent to a POSIX message queue has an associated priority. The kernel always delivers the highest-priority message first. Messages having identical priorities are delivered in FIFO order.

Priority 10 ↓ Priority 7 ↓ Priority 4 ↓ Priority 1
Priority Delivery Order
Higher Value Delivered Earlier
Equal Priority FIFO Order

24. Blocking Behavior

By default, POSIX message queue operations are blocking.

Operation Behavior
mq_receive() Blocks if the queue is empty.
mq_send() Blocks if the queue is full.

25. Non-blocking Mode

If the queue is opened with the O_NONBLOCK flag, blocking operations immediately fail instead of waiting.

Condition Result
Queue Empty mq_receive() returns -1 and sets errno to EAGAIN.
Queue Full mq_send() returns -1 and sets errno to EAGAIN.

26. Queue Full vs Queue Empty

Condition Blocking Queue Non-blocking Queue
Queue Empty Receiver Waits Error Returned
Queue Full Sender Waits Error Returned

27. Producer-Consumer Flow

Producer ↓ mq_send() ↓ Kernel Queue ↓ mq_receive() ↓ Consumer

The producer places complete messages into the queue. The consumer retrieves one complete message at a time.

28. Example: Producer

const char msg[] = "Temperature = 42"; mq_send(mq, msg, sizeof(msg), 5);

29. Example: Consumer

char buffer[128]; unsigned int priority; mq_receive(mq, buffer, sizeof(buffer), &priority);

30. Linux Debugging Commands

Command Description
ls /dev/mqueue Display active message queues.
cat /dev/mqueue/<queue_name> Display queue information (Linux).
cat /proc/sys/fs/mqueue/msg_default Default number of messages.
cat /proc/sys/fs/mqueue/msgsize_default Default message size.
man mq_send Message sending documentation.
man mq_receive Message receiving documentation.

31. Advanced Interview Questions

  1. How does mq_send() differ from write()?
  2. How are message priorities implemented?
  3. Which message is received first?
  4. What happens when a blocking queue is full?
  5. What happens when a blocking queue is empty?
  6. How does O_NONBLOCK affect queue operations?
  7. What error is returned for non-blocking queue failures?
  8. Why are message queues preferred over pipes in real-time systems?
  9. How are messages preserved inside a queue?
  10. Can multiple producers send to the same queue?

32. mq_notify()

The mq_notify() function registers a process or thread to receive asynchronous notification when a message arrives in a previously empty queue.

#include <mqueue.h> #include <signal.h> int mq_notify(mqd_t mqdes, const struct sigevent *notification);
Empty Queue ↓ mq_notify() ↓ Message Arrives ↓ Kernel Notification ↓ Application Handles Event

33. mq_getattr()

The mq_getattr() function retrieves the current attributes of a message queue.

#include <mqueue.h> int mq_getattr(mqd_t mqdes, struct mq_attr *attr);

Applications commonly use this function to determine queue capacity, message size, and the current number of queued messages.

34. mq_setattr()

The mq_setattr() function modifies selected queue attributes. According to POSIX, applications typically use it to enable or disable the O_NONBLOCK behavior through the mq_flags field. The kernel ignores attempts to change implementation-defined limits such as mq_maxmsg or mq_msgsize after queue creation.

#include <mqueue.h> int mq_setattr(mqd_t mqdes, const struct mq_attr *newattr, struct mq_attr *oldattr);

35. Complete Queue Lifecycle

mq_open() ↓ Queue Created ↓ mq_send() ↓ Messages Stored ↓ mq_receive() ↓ Messages Removed ↓ mq_close() ↓ mq_unlink() ↓ Queue Destroyed (after last close)

The queue name is removed by mq_unlink(). The underlying queue object is destroyed only after all processes have closed it.

36. Common Programming Mistakes

  • Using a receive buffer smaller than mq_msgsize.
  • Ignoring return values from queue APIs.
  • Forgetting to call mq_close().
  • Leaving queues without calling mq_unlink().
  • Using inconsistent queue names between processes.
  • Ignoring queue-full conditions.
  • Misunderstanding message priorities.

37. Best Practices

  • Define consistent queue naming conventions.
  • Allocate receive buffers using mq_msgsize.
  • Always check every API return value.
  • Use message priorities only when required by the application.
  • Close descriptors promptly after use.
  • Remove unused queues with mq_unlink().
  • Use non-blocking mode only when the application is designed for it.

38. Debugging Tips

Problem Possible Cause
mq_open() fails Incorrect queue name or insufficient permissions.
mq_send() blocks Queue has reached its maximum capacity.
mq_receive() blocks No messages are available.
EMSGSIZE error Receive buffer is smaller than mq_msgsize.
Queue remains after program exits mq_unlink() was not called.

39. Advanced Interview Questions

  1. What is the purpose of mq_notify()?
  2. When does the kernel generate a queue notification?
  3. What information does mq_getattr() return?
  4. Which queue attributes can be modified using mq_setattr()?
  5. Why must the receive buffer be at least mq_msgsize bytes?
  6. How are message priorities handled?
  7. What happens if a queue reaches mq_maxmsg?
  8. Why is mq_unlink() important?
  9. How does POSIX ensure message boundaries are preserved?
  10. When would you choose message queues instead of pipes?

40. Module Summary

In this module, we explored POSIX Message Queues in detail. We studied queue creation with mq_open(), sending and receiving messages using mq_send() and mq_receive(), asynchronous notification through mq_notify(), queue attribute management with mq_getattr() and mq_setattr(), message priorities, blocking behavior, Linux implementation details, debugging techniques, and programming best practices. POSIX Message Queues are well suited for applications that require prioritized, message-oriented communication while preserving complete message boundaries.

Knowledge Check

Concept Mastery Assessment — Module 44

Verify your conceptual understanding with 12 targeted technical assessment questions. Instant feedback and explanations are provided for every choice.

Question 1 of 12
What is the primary architectural purpose of POSIX Message Queues in operating systems?
Explanation
POSIX Message Queues is designed to manage mq_open, mq_send, mq_receive, priority-ordered messages, mq_attr configuration, asynchronous notification with mq_notify, and timeouts. within the operating system architecture.
Question 2 of 12
Which system interface or data structure is centrally associated with POSIX Message Queues?
Explanation
Under POSIX and Linux, POSIX Message Queues operates through standardized system calls and kernel control structures.
Question 3 of 12
What safety or concurrency constraint must developers consider when implementing POSIX Message Queues?
Explanation
Proper synchronization, avoidance of race conditions, and handling reentrant execution are critical when working with POSIX Message Queues.
Question 4 of 12
When a system call related to POSIX Message Queues fails in C, how does the POSIX runtime conventionally report the failure?
Explanation
Standard POSIX system calls return -1 or NULL on error, assigning an error integer (e.g. EINVAL, EPERM, EAGAIN) to the thread-local errno variable.
Question 5 of 12
What is the primary performance tradeoff associated with POSIX Message Queues?
Explanation
Operations involving POSIX Message Queues balance performance against kernel transition, memory bandwidth, and cache locality tradeoffs.
Question 6 of 12
What security principle governs access to resources in POSIX Message Queues?
Explanation
The kernel validates credentials, effective permissions, and Linux capabilities before granting access to protected operations.
Question 7 of 12
How does execution of POSIX Message Queues transition between User Space and Kernel Space?
Explanation
User space transitions to kernel mode securely via software traps or SYSCALL instructions that switch processor rings to Ring 0.
Question 8 of 12
What happens to resources allocated by POSIX Message Queues when the owning process terminates?
Explanation
Process resources (open fds, memory maps) are automatically reclaimed by the kernel on termination, while kernel-persistent objects survive.
Question 9 of 12
In production Linux server environments, how is POSIX Message Queues optimized for high throughput?
Explanation
Linux optimizes throughput via zero-copy data paths, asynchronous kernel events, and scalable concurrency primitives.
Question 10 of 12
What standard governs the portability of POSIX Message Queues across Unix, Linux, and macOS platforms?
Explanation
IEEE POSIX standards define consistent APIs across Unix-like platforms ensuring portable source code execution.
Question 11 of 12
Which command-line diagnostic tool is most effective for inspecting and troubleshooting POSIX Message Queues at runtime?
Explanation
Utilities like strace, lsof, and the /proc filesystem provide direct visibility into kernel interactions and resource status.
Question 12 of 12
What is a critical production best practice when developing systems software involving POSIX Message Queues?
Explanation
Defensive programming requires explicit error checking on all system operations, proper resource cleanup, and avoiding memory corruption.
0 / 12 (0%)
Great job! Review the concepts above and proceed when ready.
ADVERTISEMENT
Responsive Ad Unit • Technical Courses & Certifications