1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/MQueues.html
2025-01-28 10:11:14 +01:00

560 lines
No EOL
44 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>3.6. Message Passing With Message Queues &mdash; Computer Systems Fundamentals</title>
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
<style>
.underline { text-decoration: underline; }
</style>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.4.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": {
scale: "80"
}
});
</script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
<link rel="next" title="7. Shared Memory" href="ShMem.html" />
<link rel="prev" title="5. POSIX vs. System V IPC" href="POSIXvSysV.html" />
</head><body>
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
<!-- Show a navbar toggler on mobile -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="defaultNavbars">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle jmu-gold rounded" href="MQueues.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
<a class="dropdown-item" tabindex="-1" href="MQueues.html#"><b>Chapter 1</b></a>
<a class="dropdown-item" href="IntroConcSysOverview.html">&nbsp;&nbsp;&nbsp;1.1. Introduction to Concurrent Systems</a>
<a class="dropdown-item" href="SysAndModels.html">&nbsp;&nbsp;&nbsp;1.2. Systems and Models</a>
<a class="dropdown-item" href="Themes.html">&nbsp;&nbsp;&nbsp;1.3. Themes and Guiding Principles</a>
<a class="dropdown-item" href="Architectures.html">&nbsp;&nbsp;&nbsp;1.4. System Architectures</a>
<a class="dropdown-item" href="StateModels.html">&nbsp;&nbsp;&nbsp;1.5. State Models in UML</a>
<a class="dropdown-item" href="SequenceModels.html">&nbsp;&nbsp;&nbsp;1.6. Sequence Models in UML</a>
<a class="dropdown-item" href="StateModelImplementation.html">&nbsp;&nbsp;&nbsp;1.7. Extended Example: State Model Implementation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
<a class="dropdown-item" href="ProcessesOverview.html">&nbsp;&nbsp;&nbsp;2.1. Processes and OS Basics</a>
<a class="dropdown-item" href="Multiprogramming.html">&nbsp;&nbsp;&nbsp;2.2. Processes and Multiprogramming</a>
<a class="dropdown-item" href="KernelMechanics.html">&nbsp;&nbsp;&nbsp;2.3. Kernel Mechanics</a>
<a class="dropdown-item" href="Syscall.html">&nbsp;&nbsp;&nbsp;2.4. System Call Interface</a>
<a class="dropdown-item" href="ProcessCycle.html">&nbsp;&nbsp;&nbsp;2.5. Process Life Cycle</a>
<a class="dropdown-item" href="UnixFile.html">&nbsp;&nbsp;&nbsp;2.6. The UNIX File Abstraction</a>
<a class="dropdown-item" href="EventsSignals.html">&nbsp;&nbsp;&nbsp;2.7. Events and Signals</a>
<a class="dropdown-item" href="Extended2Processes.html">&nbsp;&nbsp;&nbsp;2.8. Extended Example: Listing Files with Processes</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
<a class="dropdown-item" href="IPCOverview.html">&nbsp;&nbsp;&nbsp;3.1. Concurrency with IPC</a>
<a class="dropdown-item" href="IPCModels.html">&nbsp;&nbsp;&nbsp;3.2. IPC Models</a>
<a class="dropdown-item" href="Pipes.html">&nbsp;&nbsp;&nbsp;3.3. Pipes and FIFOs</a>
<a class="dropdown-item" href="MMap.html">&nbsp;&nbsp;&nbsp;3.4. Shared Memory With Memory-mapped Files</a>
<a class="dropdown-item" href="POSIXvSysV.html">&nbsp;&nbsp;&nbsp;3.5. POSIX vs. System V IPC</a>
<a class="dropdown-item" href="MQueues.html">&nbsp;&nbsp;&nbsp;3.6. Message Passing With Message Queues</a>
<a class="dropdown-item" href="ShMem.html">&nbsp;&nbsp;&nbsp;3.7. Shared Memory</a>
<a class="dropdown-item" href="IPCSems.html">&nbsp;&nbsp;&nbsp;3.8. Semaphores</a>
<a class="dropdown-item" href="Extended3Bash.html">&nbsp;&nbsp;&nbsp;3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
<a class="dropdown-item" href="SocketsOverview.html">&nbsp;&nbsp;&nbsp;4.1. Networked Concurrency</a>
<a class="dropdown-item" href="FiveLayer.html">&nbsp;&nbsp;&nbsp;4.2. The TCP/IP Internet Model</a>
<a class="dropdown-item" href="NetApps.html">&nbsp;&nbsp;&nbsp;4.3. Network Applications and Protocols</a>
<a class="dropdown-item" href="Sockets.html">&nbsp;&nbsp;&nbsp;4.4. The Socket Interface</a>
<a class="dropdown-item" href="TCPSockets.html">&nbsp;&nbsp;&nbsp;4.5. TCP Socket Programming: HTTP</a>
<a class="dropdown-item" href="UDPSockets.html">&nbsp;&nbsp;&nbsp;4.6. UDP Socket Programming: DNS</a>
<a class="dropdown-item" href="AppBroadcast.html">&nbsp;&nbsp;&nbsp;4.7. Application-Layer Broadcasting: DHCP</a>
<a class="dropdown-item" href="Extended4CGI.html">&nbsp;&nbsp;&nbsp;4.8. Extended Example: CGI Web Server</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
<a class="dropdown-item" href="InternetOverview.html">&nbsp;&nbsp;&nbsp;5.1. The Internet and Connectivity</a>
<a class="dropdown-item" href="AppLayer.html">&nbsp;&nbsp;&nbsp;5.2. Application Layer: Overlay Networks</a>
<a class="dropdown-item" href="TransLayer.html">&nbsp;&nbsp;&nbsp;5.3. Transport Layer</a>
<a class="dropdown-item" href="NetSec.html">&nbsp;&nbsp;&nbsp;5.4. Network Security Fundamentals</a>
<a class="dropdown-item" href="NetLayer.html">&nbsp;&nbsp;&nbsp;5.5. Network Layer: IP</a>
<a class="dropdown-item" href="LinkLayer.html">&nbsp;&nbsp;&nbsp;5.6. Link Layer</a>
<a class="dropdown-item" href="Wireless.html">&nbsp;&nbsp;&nbsp;5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
<a class="dropdown-item" href="Extended5DNS.html">&nbsp;&nbsp;&nbsp;5.8. Extended Example: DNS client</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
<a class="dropdown-item" href="ThreadsOverview.html">&nbsp;&nbsp;&nbsp;6.1. Concurrency with Multithreading</a>
<a class="dropdown-item" href="ProcVThreads.html">&nbsp;&nbsp;&nbsp;6.2. Processes vs. Threads</a>
<a class="dropdown-item" href="RaceConditions.html">&nbsp;&nbsp;&nbsp;6.3. Race Conditions and Critical Sections</a>
<a class="dropdown-item" href="POSIXThreads.html">&nbsp;&nbsp;&nbsp;6.4. POSIX Thread Library</a>
<a class="dropdown-item" href="ThreadArgs.html">&nbsp;&nbsp;&nbsp;6.5. Thread Arguments and Return Values</a>
<a class="dropdown-item" href="ImplicitThreads.html">&nbsp;&nbsp;&nbsp;6.6. Implicit Threading and Language-based Threads</a>
<a class="dropdown-item" href="Extended6Input.html">&nbsp;&nbsp;&nbsp;6.7. Extended Example: Keyboard Input Listener</a>
<a class="dropdown-item" href="Extended6Primes.html">&nbsp;&nbsp;&nbsp;6.8. Extended Example: Concurrent Prime Number Search</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
<a class="dropdown-item" href="SynchOverview.html">&nbsp;&nbsp;&nbsp;7.1. Synchronization Primitives</a>
<a class="dropdown-item" href="CritSect.html">&nbsp;&nbsp;&nbsp;7.2. Critical Sections and Peterson's Solution</a>
<a class="dropdown-item" href="Locks.html">&nbsp;&nbsp;&nbsp;7.3. Locks</a>
<a class="dropdown-item" href="Semaphores.html">&nbsp;&nbsp;&nbsp;7.4. Semaphores</a>
<a class="dropdown-item" href="Barriers.html">&nbsp;&nbsp;&nbsp;7.5. Barriers</a>
<a class="dropdown-item" href="Condvars.html">&nbsp;&nbsp;&nbsp;7.6. Condition Variables</a>
<a class="dropdown-item" href="Deadlock.html">&nbsp;&nbsp;&nbsp;7.7. Deadlock</a>
<a class="dropdown-item" href="Extended7Events.html">&nbsp;&nbsp;&nbsp;7.8. Extended Example: Event Log File</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
<a class="dropdown-item" href="SynchProblemsOverview.html">&nbsp;&nbsp;&nbsp;8.1. Synchronization Patterns and Problems</a>
<a class="dropdown-item" href="SynchDesign.html">&nbsp;&nbsp;&nbsp;8.2. Basic Synchronization Design Patterns</a>
<a class="dropdown-item" href="ProdCons.html">&nbsp;&nbsp;&nbsp;8.3. Producer-Consumer Problem</a>
<a class="dropdown-item" href="ReadWrite.html">&nbsp;&nbsp;&nbsp;8.4. Readers-Writers Problem</a>
<a class="dropdown-item" href="DiningPhil.html">&nbsp;&nbsp;&nbsp;8.5. Dining Philosophers Problem and Deadlock</a>
<a class="dropdown-item" href="CigSmokers.html">&nbsp;&nbsp;&nbsp;8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
<a class="dropdown-item" href="Extended8ModExp.html">&nbsp;&nbsp;&nbsp;8.7. Extended Example: Parallel Modular Exponentiation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
<a class="dropdown-item" href="ParallelDistributedOverview.html">&nbsp;&nbsp;&nbsp;9.1. Parallel and Distributed Systems</a>
<a class="dropdown-item" href="ParVConc.html">&nbsp;&nbsp;&nbsp;9.2. Parallelism vs. Concurrency</a>
<a class="dropdown-item" href="ParallelDesign.html">&nbsp;&nbsp;&nbsp;9.3. Parallel Design Patterns</a>
<a class="dropdown-item" href="Scaling.html">&nbsp;&nbsp;&nbsp;9.4. Limits of Parallelism and Scaling</a>
<a class="dropdown-item" href="DistTiming.html">&nbsp;&nbsp;&nbsp;9.5. Timing in Distributed Environments</a>
<a class="dropdown-item" href="DistDataStorage.html">&nbsp;&nbsp;&nbsp;9.6. Reliable Data Storage and Location</a>
<a class="dropdown-item" href="DistConsensus.html">&nbsp;&nbsp;&nbsp;9.7. Consensus in Distributed Systems</a>
<a class="dropdown-item" href="Extended9Blockchain.html">&nbsp;&nbsp;&nbsp;9.8. Extended Example: Blockchain Proof-of-Work</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Appendix A</b></a>
<a class="dropdown-item" href="CLangOverview.html">&nbsp;&nbsp;&nbsp;A.1. C Language Reintroduction</a>
<a class="dropdown-item" href="Debugging.html">&nbsp;&nbsp;&nbsp;A.2. Documentation and Debugging</a>
<a class="dropdown-item" href="BasicTypes.html">&nbsp;&nbsp;&nbsp;A.3. Basic Types and Pointers</a>
<a class="dropdown-item" href="Arrays.html">&nbsp;&nbsp;&nbsp;A.4. Arrays, Structs, Enums, and Type Definitions</a>
<a class="dropdown-item" href="Functions.html">&nbsp;&nbsp;&nbsp;A.5. Functions and Scope</a>
<a class="dropdown-item" href="Pointers.html">&nbsp;&nbsp;&nbsp;A.6. Pointers and Dynamic Allocation</a>
<a class="dropdown-item" href="Strings.html">&nbsp;&nbsp;&nbsp;A.7. Strings</a>
<a class="dropdown-item" href="FunctionPointers.html">&nbsp;&nbsp;&nbsp;A.8. Function Pointers</a>
<a class="dropdown-item" href="Files.html">&nbsp;&nbsp;&nbsp;A.9. Files</a>
</div>
</li>
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/MQueues.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="POSIXvSysV.html">3.5. POSIX vs. System V IPC</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="ShMem.html">3.7. Shared Memory</a>&#160;&#160;»
</div>
<br />
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
<script type="text/javascript" src="_static/js/config.js"></script>
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
<div class="container">
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "MQueues";ODSA.SETTINGS.MODULE_LONG_NAME = "Message Passing With Message Queues";ODSA.SETTINGS.MODULE_CHAPTER = "Concurrency with IPC"; ODSA.SETTINGS.BUILD_DATE = "2021-06-11 17:38:24"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="message-passing-with-message-queues">
<h1>3.6. Message Passing With Message Queues<a class="headerlink" href="MQueues.html#message-passing-with-message-queues" title="Permalink to this headline"></a></h1>
<p><a class="reference internal" href="Glossary.html#term-message-queue"><span class="xref std std-term">Message queues</span></a> allow processes to communicate by exchanging structured
messages. As with <a class="reference internal" href="Glossary.html#term-pipe"><span class="xref std std-term">pipes</span></a> and <a class="reference internal" href="Glossary.html#term-fifo"><span class="xref std std-term">FIFOs</span></a>, processes can message queues follow
a <a class="reference internal" href="Glossary.html#term-message-passing"><span class="xref std std-term">message passing</span></a> IPC model for exchanging data in discrete messages. However, message
queues differ from pipes in several important ways:</p>
<blockquote>
<div><ul class="simple">
<li>While pipes send unstructured byte streams, messages are sent as distinct units. When a message is
retrieved from the queue, the process receives exactly one message in its entirety; there is no way
to retrieve part of a message and leave the rest in the queue.</li>
<li>Message queues use special identifiers, rather than file descriptors. As a result, message queues
require special functions for sending and receiving data, rather than the standard file interface functions.</li>
<li>Message queues have associated metadata that allows processes to specify the order in which
messages are received. That is, message queues do not require or guarantee a first-in, first-out ordering.</li>
<li>Message queues have kernel-level persistence and use special functions or utilities for removing
them. Killing the process will not remove the message queue.</li>
</ul>
</div></blockquote>
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
<p>It is important to understand the difference between messages and byte streams. Assume that one
process has made 100 calls to a function to transmit a single byte at a time. If pipes or FIFOs are
used, all of this data can be retrieved with a single call to <code class="docutils literal notranslate"><span class="pre">read()</span></code> that requests 100 bytes.
In the case of message queues, each byte is a distinct message that must be retrieved individually.
There is no short-cut to retrieve all of the data at once.</p>
<p>Now, assume that the sending process sent all 100 bytes with one function call. If the processes are
using a pipe or FIFO and the receiver requests only 50 bytes with <code class="docutils literal notranslate"><span class="pre">read()</span></code>, that process will
retrieve exactly 50 bytes. However, if message queues are used, the bytes would be converted into a
single message; the size of the message is determined based on the parameters used to set up the
message queue. For instance, the default message size for POSIX message queues in Linux is 8192
bytes. If the receiving process requests less than this (such as requesting only 50 bytes), <strong>it
will receive nothing</strong>. Ignoring the difference between a message and a byte stream can lead to
unexpected behavior that causes unanticipated failures.</p>
</div>
<p>POSIX message queues also provide a number of key features that are not available in other
interfaces, such as System V:</p>
<blockquote>
<div><ul class="simple">
<li>A POSIX message queue is only removed once it is closed by all processes currently using it.</li>
<li>POSIX message queues include an asynchronous notification feature that allows processes to alerted
when a message is available.</li>
<li>POSIX message metadata includes an associated priority level. The first message retrieved is
always the one with the highest priority level.</li>
<li>POSIX message queues allow application designers to specify attributes (such as message size or
capacity of the queue) via optional parameters passed when opening the queue.</li>
</ul>
</div></blockquote>
<p><a href="MQueues.html#ipcprio">Figure 3.6.2</a> illustrates a key point about POSIX message queues. In this example,
assume that the messages A, B, C, D, and E have been inserted (in that order). POSIX message queues
use non-negative values for the priority, with 0 being lowest. As such, messages C and D are at the
front of the queue because they have the highest priority. Within a single priority level, though,
the queue uses a first-in, first-out ordering.</p>
<div class="figure mb-2 align-center" id="id1">
<span id="ipcprio"></span><a class="reference internal image-reference" href="_images/CSF-Images.3.5.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="POSIX message queues are priority-based, with 0 as the lowest priority" src="_images/CSF-Images.3.5.png" style="width: 60%;" /></a>
<p class="caption align-center px-3"><span class="caption-text"> Figure 3.6.2: POSIX message queues are priority-based, with 0 as the lowest priority</span></p>
</div>
<div class="section" id="posix-message-queues">
<h2>3.6.1. POSIX Message Queues<a class="headerlink" href="MQueues.html#posix-message-queues" title="Permalink to this headline"></a></h2>
<p>There are six functions typically used for setting up and using POSIX <a class="reference internal" href="Glossary.html#term-message-queue"><span class="xref std std-term">message queues</span></a>.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;mqueue.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">mqd_t</span> <span class="pre">mq_open</span> <span class="pre">(const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">int</span> <span class="pre">oflag,</span> <span class="pre">...</span> <span class="pre">/*</span> <span class="pre">mode_t</span> <span class="pre">mode,</span> <span class="pre">struct</span> <span class="pre">mq_attr</span> <span class="pre">*attr</span> <span class="pre">*/);</span></code></dt>
<dd>Open (and possibly create) a POSIX message queue.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">mq_getattr(mqd_t</span> <span class="pre">mqdes,</span> <span class="pre">struct</span> <span class="pre">mq_attr</span> <span class="pre">*attr);</span></code></dt>
<dd>Get the attributes associated with a given message queue.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">mq_close</span> <span class="pre">(mqd_t</span> <span class="pre">mqdes);</span></code></dt>
<dd>Close a message queue.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">mq_unlink</span> <span class="pre">(const</span> <span class="pre">char</span> <span class="pre">*name);</span></code></dt>
<dd>Initiate deletion of a message queue.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">mq_send</span> <span class="pre">(mqd_t</span> <span class="pre">mqdes,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*msg_ptr,</span> <span class="pre">size_t</span> <span class="pre">msg_len,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">msg_prio);</span></code></dt>
<dd>Send the message pointed to by msg_ptr with priority msg_prio.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ssize_t</span> <span class="pre">mq_receive</span> <span class="pre">(mqd_t</span> <span class="pre">mqdes,</span> <span class="pre">char</span> <span class="pre">*msg_ptr,</span> <span class="pre">size_t</span> <span class="pre">msg_len,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">*msg_prio);</span></code></dt>
<dd>Receive a message into a buffer pointed to by msg_ptr and get its priority msg_prio.</dd>
</dl>
</div>
<p>As with other POSIX IPC open functions, <code class="docutils literal notranslate"><span class="pre">mq_open()</span></code> includes both an <code class="docutils literal notranslate"><span class="pre">oflag</span></code> and <code class="docutils literal notranslate"><span class="pre">mode</span></code>
parameter. In addition, the fourth parameter (<code class="docutils literal notranslate"><span class="pre">attr</span></code>) is used to specify attributes about the
message queue, such as the message size or the capacity of the queue. Note that calls to
<code class="docutils literal notranslate"><span class="pre">mq_open()</span></code> must have exactly 2 or 4 parameters. Both the <code class="docutils literal notranslate"><span class="pre">mode</span></code> and <code class="docutils literal notranslate"><span class="pre">attr</span></code> parameters must be
included when creating a new message queue. When opening a connection to an existing message queue,
both of these parameters are omitted. To use the system defaults when setting up a message queue,
pass <code class="docutils literal notranslate"><span class="pre">NULL</span></code> as the fourth parameter to <code class="docutils literal notranslate"><span class="pre">mq_open()</span></code>. <a class="reference external" href="MQueues.html#cl3-7">Code Listing 3.7</a> creates a message queue for
writing and sends a simple message.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-7"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.7:</span>
<span class="cm"> Sending &quot;HELLO&quot; through a POSIX message queue</span>
<span class="cm"> */</span>
<span class="cm">/* Create and open a message queue for writing */</span>
<span class="n">mqd_t</span> <span class="n">mqd</span> <span class="o">=</span> <span class="n">mq_open</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_MQ&quot;</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_EXCL</span> <span class="o">|</span> <span class="n">O_WRONLY</span><span class="p">,</span> <span class="mo">0600</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Ensure the creation was successful */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">mqd</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">perror</span> <span class="p">(</span><span class="s">&quot;mq_open&quot;</span><span class="p">);</span>
<span class="n">exit</span> <span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Send &quot;HELLO&quot; as a message with priority 10, then close the queue.</span>
<span class="cm"> Note the size is 6 to include the null byte &#39;\0&#39;. */</span>
<span class="n">mq_send</span> <span class="p">(</span><span class="n">mqd</span><span class="p">,</span> <span class="s">&quot;HELLO&quot;</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
<span class="n">mq_close</span> <span class="p">(</span><span class="n">mqd</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p><a class="reference external" href="MQueues.html#cl3-8">Code Listing 3.8</a> illustrates a standard approach for retrieving a message from the queue. The
<code class="docutils literal notranslate"><span class="pre">msg_len</span></code> parameter for receiving messages requires special attention. The use of this parameter
for <code class="docutils literal notranslate"><span class="pre">mq_send()</span></code> is intuitive and matches the behavior of functions like <code class="docutils literal notranslate"><span class="pre">write()</span></code> and
<code class="docutils literal notranslate"><span class="pre">strncpy()</span></code>: <code class="docutils literal notranslate"><span class="pre">msg_len</span></code> specifies the maximum number of characters in the string identified by
<code class="docutils literal notranslate"><span class="pre">msg_ptr</span></code> that will be sent. However, when receiving messages, <code class="docutils literal notranslate"><span class="pre">msg_len</span></code> must match the size of
a message. As such, the standard approach is to use <code class="docutils literal notranslate"><span class="pre">mq_getattr()</span></code> and access the <code class="docutils literal notranslate"><span class="pre">mq_msgsize</span></code>
field of the <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">mq_attr</span></code> returned.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-8"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.8:</span>
<span class="cm"> Opening a POSIX message queue and retrieving a message</span>
<span class="cm"> */</span>
<span class="cm">/* Open the message queue for reading */</span>
<span class="n">mqd_t</span> <span class="n">mqd</span> <span class="o">=</span> <span class="n">mq_open</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_MQ&quot;</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">mqd</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="cm">/* Get the message queue attributes */</span>
<span class="k">struct</span> <span class="n">mq_attr</span> <span class="n">attr</span><span class="p">;</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">mq_getattr</span> <span class="p">(</span><span class="n">mqd</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">attr</span><span class="p">)</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="n">attr</span><span class="p">.</span><span class="n">mq_msgsize</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">buffer</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Retrieve message from the queue and get its priority level */</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">priority</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">((</span><span class="n">mq_receive</span> <span class="p">(</span><span class="n">mqd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">attr</span><span class="p">.</span><span class="n">mq_msgsize</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">priority</span><span class="p">))</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Failed to receive message</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="k">else</span>
<span class="nf">printf</span> <span class="p">(</span><span class="s">&quot;Received [priority %u]: &#39;%s&#39;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">priority</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
<span class="cm">/* Clean up the allocated memory and message queue */</span>
<span class="n">free</span> <span class="p">(</span><span class="n">buffer</span><span class="p">);</span>
<span class="n">buffer</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">mq_close</span> <span class="p">(</span><span class="n">mqd</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
<p>In many instances, it is common practice to create a statically sized buffer as a local variable
(such as <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">buffer[100];</span></code>) and use the buffer size when reading data from some other source.
However, the following line of code <strong>will not work</strong> with message queues:</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-2 mb-3 notranslate"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="kt">int</span> <span class="n">bytes_read</span> <span class="o">=</span> <span class="n">mq_receive</span> <span class="p">(</span><span class="n">mqid</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">prio</span><span class="p">);</span>
</pre></div>
</div>
<p>The reason for this is that the <code class="docutils literal notranslate"><span class="pre">msg_len</span></code> parameter does not exactly match the message queues
message size (a common default is 8192, but it depends on the system). As such, the message queue
will interpret this as a request to read less than a full message and will return nothing.</p>
</div>
<p>Unlike pipes, message queues can be used to send <code class="docutils literal notranslate"><span class="pre">struct</span></code> instances, even if some of the fields
contain the value 0. (Pipes treat a byte value of 0 as the null byte and stop at that point.)
Consider the following trivial <code class="docutils literal notranslate"><span class="pre">struct</span></code> declaration:</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
2
3
4
5</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="k">struct</span> <span class="n">message</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">y</span><span class="p">;</span>
<span class="kt">long</span> <span class="n">z</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</td></tr></table></div>
<p>As shown in <a class="reference external" href="MQueues.html#cl3-9">Code Listing 3.9</a>, sending the message with POSIX message queues works almost exactly as
shown previously with a <code class="docutils literal notranslate"><span class="pre">char</span></code> array. The only differences are the casting of the <code class="docutils literal notranslate"><span class="pre">msg_ptr</span></code>
pointer and that the <code class="docutils literal notranslate"><span class="pre">msg_len</span></code> parameter is based on the size of the <code class="docutils literal notranslate"><span class="pre">struct</span></code>. Similarly, the
only difference with reading is the casting of the <code class="docutils literal notranslate"><span class="pre">msg_ptr</span></code> to the <code class="docutils literal notranslate"><span class="pre">struct</span></code> type.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-9"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.9:</span>
<span class="cm"> Retrieving a structured POSIX message</span>
<span class="cm"> */</span>
<span class="k">struct</span> <span class="n">message</span> <span class="n">msg</span><span class="p">;</span>
<span class="n">msg</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">msg</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="sc">&#39;q&#39;</span><span class="p">;</span>
<span class="n">msg</span><span class="p">.</span><span class="n">z</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="cm">/* Sending a struct works identically to a char array */</span>
<span class="n">mq_send</span> <span class="p">(</span><span class="n">mqd</span><span class="p">,</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="k">struct</span> <span class="n">message</span><span class="p">),</span> <span class="mi">10</span><span class="p">);</span>
<span class="cm">/* When reading, use a char* buffer and explicitly cast */</span>
<span class="k">if</span> <span class="p">((</span><span class="n">mq_receive</span> <span class="p">(</span><span class="n">mqd</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">attr</span><span class="p">.</span><span class="n">mq_msgsize</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">prio</span><span class="p">))</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">message</span> <span class="o">*</span><span class="n">msg</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">message</span> <span class="o">*</span><span class="p">)</span><span class="n">buffer</span><span class="p">;</span>
<span class="cm">/* Retrieve message fields here */</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The default behavior for POSIX message queues is to perform <a class="reference internal" href="Glossary.html#term-blocking-i-o"><span class="xref std std-term">blocking I/O</span></a> when writing to a
full queue (or reading from an empty one). If this behavior is undesirable, there are three
alternatives that can be used. The first is to include the <code class="docutils literal notranslate"><span class="pre">O_NONBLOCK</span></code> option in the <code class="docutils literal notranslate"><span class="pre">oflag</span></code>
bit mask to open the queue in non-blocking mode. If the queue is ever full, <code class="docutils literal notranslate"><span class="pre">mq_send()</span></code> will
return an error without blocking. The other option is to use <code class="docutils literal notranslate"><span class="pre">mq_timedsend()</span></code> and
<code class="docutils literal notranslate"><span class="pre">mq_timedreceive()</span></code>, which use an additional parameter (<code class="docutils literal notranslate"><span class="pre">abs_timeout</span></code>) to specify the maximum
amount of time to wait when blocked. Finally, rather than attempting to retrieve a message that may
not have been sent, a process can use <code class="docutils literal notranslate"><span class="pre">mq_notify()</span></code> to request an asynchronous notification that a
message has been sent. Interested readers should consult the language documentation for more
information on these functions.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;mqueue.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">mq_timedsend</span> <span class="pre">(mqd_t</span> <span class="pre">mqdes,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*msg_ptr,</span> <span class="pre">size_t</span> <span class="pre">msg_len,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">msg_prio,</span> <span class="pre">const</span> <span class="pre">struct</span> <span class="pre">timespec</span> <span class="pre">*abs_timeout);</span></code></dt>
<dd>Try to send a message, but specify a maximum time limit (abs_timeout) for blocking.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ssize_t</span> <span class="pre">mq_timedreceive</span> <span class="pre">(mqd_t</span> <span class="pre">mqdes,</span> <span class="pre">char</span> <span class="pre">*msg_ptr,</span> <span class="pre">size_t</span> <span class="pre">msg_len,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">*msg_prio,</span> <span class="pre">const</span> <span class="pre">struct</span> <span class="pre">timespec</span> <span class="pre">*abs_timeout);</span></code></dt>
<dd>Try to receive a message, but specify a maximum time limit (abs_timeout) for blocking.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">mq_notify</span> <span class="pre">(mqd_t</span> <span class="pre">mqdes,</span> <span class="pre">const</span> <span class="pre">struct</span> <span class="pre">sigevent</span> <span class="pre">*notification);</span></code></dt>
<dd>Request asynchronous notification when a message is placed in the queue.</dd>
</dl>
</div>
<div
id="IPCMqueueSumm"
class="embedContainer"
data-exer-name="IPCMqueueSumm"
data-long-name="IPC message queue questions"
data-short-name="IPCMqueueSumm"
data-frame-src="../../../Exercises/IPC/IPCMqueueSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=MQueues"
data-frame-width="950"
data-frame-height="550"
data-external="false"
data-points="0"
data-required="False"
data-showhide="show"
data-threshold="3"
data-type="ka"
data-exer-id="">
<div class="center">
<div id="IPCMqueueSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="POSIXvSysV.html">3.5. POSIX vs. System V IPC</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="ShMem.html">3.7. Shared Memory</a>&#160;&#160;»
</div>
</div>
<br />
<div class="row jmu-dark-purple-bg">
<div class="col-md-12">
<center>
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
</center>
</div>
</div>
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>