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
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.
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.
6. Queue Attributes
Each queue maintains operational attributes represented by the
struct mq_attr structure.
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:
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
- What is a POSIX message queue?
- How does it differ from a pipe?
- Why are message boundaries important?
- What type represents a message queue descriptor?
- What information does
struct mq_attrcontain? - What is the purpose of
mq_maxmsg? - What is stored in
mq_curmsgs? - Where are POSIX message queues commonly exposed on Linux?
- Why are message priorities useful?
- Which applications commonly use message queues?
11. mq_open()
The mq_open() function creates a new POSIX message queue
or opens an existing one.
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.
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.
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
18. Example: Creating a Queue
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
- What is the purpose of
mq_open()? - When are the
modeandattrarguments required? - What happens if
O_CREATis omitted? - How does
O_EXCLwork? - Which type is returned by
mq_open()? - What does
O_NONBLOCKchange? - What happens if the queue already exists?
- Where are message queues commonly visible on Linux?
- How are permissions assigned to a new queue?
- 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.
22. mq_receive()
The mq_receive() function removes the highest-priority
message currently available from the queue.
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 | 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
The producer places complete messages into the queue. The consumer retrieves one complete message at a time.
28. Example: Producer
29. Example: Consumer
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
- How does
mq_send()differ fromwrite()? - How are message priorities implemented?
- Which message is received first?
- What happens when a blocking queue is full?
- What happens when a blocking queue is empty?
- How does
O_NONBLOCKaffect queue operations? - What error is returned for non-blocking queue failures?
- Why are message queues preferred over pipes in real-time systems?
- How are messages preserved inside a queue?
- 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.
33. mq_getattr()
The mq_getattr() function retrieves the current attributes
of a message queue.
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.
35. Complete Queue Lifecycle
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
- What is the purpose of
mq_notify()? - When does the kernel generate a queue notification?
- What information does
mq_getattr()return? - Which queue attributes can be modified using
mq_setattr()? - Why must the receive buffer be at least
mq_msgsizebytes? - How are message priorities handled?
- What happens if a queue reaches
mq_maxmsg? - Why is
mq_unlink()important? - How does POSIX ensure message boundaries are preserved?
- 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.
Concept Mastery Assessment — Module 44
Verify your conceptual understanding with 12 targeted technical assessment questions. Instant feedback and explanations are provided for every choice.