D. Kalinsky Associates
 Home  |  Online Learning  |  Resources  |  About Us  |  Contact  |  Site Map  
Online Training Session:         Messages for Intertask Communication
“Indirect” Message Passing
•  Messages are Sent from Task to Task via Queues
•  Not Sent Directly from Task to Task
•  Message Queues are Separate RTOS Objects
•  Need to be Created by RTOS Service Calls
•  Caution: Messages are Copied by the RTOS
         … as they Enter/Exit the Queue
                         --> Usually Copied Twice
•  Example: RTOS "X":  msg_send() copies Message into "Hidden" RTOS Memory
msg_receive() copies Message out of "Hidden" RTOS Memory
Previous                    Page 2 of 9                 Next

Most real-time operating systems use a technique we'll call "Indirect" Message Passing.   In this approach,
messages are NOT sent straight from task to task, but rather through an intermediary 'entity' called a "
".  (I'm using the word 'entity' because I don't want to use the word 'object'.)  The idea is that one task will send
messages into the queue; and then, perhaps later on, another task will fetch the messages from the queue.

In the diagram on this page, the message queue is shown in the middle, with the message sender task shown on
the left and the message receiver task on the right.  The envelope in the diagram represents a message, and is
shown as it is being fetched from the queue for the receiver task.

Before a task can send a message to another task, the Message Queue needs to be created.  This is done by asking
that your RTOS create the queue, using an RTOS service call named something like "
queue_create()". Any task can
ask to create the queue; it doesn't have to be the message sender task or the message receiver task.  But, both the
message sender and message receiver tasks need to be informed of the identity of the queue (this is usually a 32-bit
number, called a "Queue-Identifier"), in order for them to communicate through the queue.

Typically, an embedded or real-time application using "Indirect" Message Passing will contain lots of message
queues.  It is simplest to design software so that there's a separate queue for every pair of tasks that need to transfer
data from one to the other.  If the data transfer is bi-directional, that pair of tasks will typically need two queues -- one
for each direction of data transfer.  If different kinds of data are being transferred, separate queues will usually be
used for the separate kinds of data.

Many real-time operating systems that use "Indirect" Message Passing work by copying the message data into a
"hidden" area of RAM memory, when asked by a task to "send" a message.  You can think of this "hidden" area of RAM
as the actual "queue" -- even though it isn't organized in the way we'd expect a queue to be organized.  When a task
wants to "receive" a message, the RTOS copies the message data out of the hidden area of RAM and delivers it to the
requesting task.   This "hiding" of the message while it's in the queue, is done so that no task can change or read the
message data while it's enqueued -- thus preventing nasty access collisions that might cause data corruptions
("mutual exclusion violations").  But there's also a 'down-side':  Copying the message data into and out of this "hidden"
area can be a lot of RTOS performance overhead, especially for long messages.

How can a programmer make message passing happen?  A task that has prepared a message for sending, can
make an RTOS service call named something like "
msg_send()".  A task that wants to receive a message, can make
an RTOS service call named something like "
msg_receive()".   The precise names of the service calls and their
parameters, are slightly different for each specific RTOS.
© Copyright 2010, D. Kalinsky Associates, All Rights Reserved.
This page Updated January 1, 2010
Producer Task
(sends messages)
Consumer Task
(receives messages)