560 lines
44 KiB
HTML
560 lines
44 KiB
HTML
|
|
|||
|
<!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 — 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"> 1.1. Introduction to Concurrent Systems</a>
|
|||
|
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
|||
|
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
|||
|
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
|||
|
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
|||
|
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
|||
|
<a class="dropdown-item" href="StateModelImplementation.html"> 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"> 2.1. Processes and OS Basics</a>
|
|||
|
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
|||
|
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
|||
|
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
|||
|
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
|||
|
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
|||
|
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
|||
|
<a class="dropdown-item" href="Extended2Processes.html"> 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"> 3.1. Concurrency with IPC</a>
|
|||
|
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
|||
|
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
|||
|
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
|||
|
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
|||
|
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
|||
|
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
|||
|
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
|||
|
<a class="dropdown-item" href="Extended3Bash.html"> 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"> 4.1. Networked Concurrency</a>
|
|||
|
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
|||
|
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
|||
|
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
|||
|
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
|||
|
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
|||
|
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
|||
|
<a class="dropdown-item" href="Extended4CGI.html"> 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"> 5.1. The Internet and Connectivity</a>
|
|||
|
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
|||
|
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
|||
|
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
|||
|
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
|||
|
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
|||
|
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
|||
|
<a class="dropdown-item" href="Extended5DNS.html"> 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"> 6.1. Concurrency with Multithreading</a>
|
|||
|
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
|||
|
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
|||
|
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
|||
|
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
|||
|
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
|||
|
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
|||
|
<a class="dropdown-item" href="Extended6Primes.html"> 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"> 7.1. Synchronization Primitives</a>
|
|||
|
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
|||
|
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
|||
|
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
|||
|
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
|||
|
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
|||
|
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
|||
|
<a class="dropdown-item" href="Extended7Events.html"> 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"> 8.1. Synchronization Patterns and Problems</a>
|
|||
|
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
|||
|
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
|||
|
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
|||
|
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
|||
|
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
|||
|
<a class="dropdown-item" href="Extended8ModExp.html"> 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"> 9.1. Parallel and Distributed Systems</a>
|
|||
|
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
|||
|
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
|||
|
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
|||
|
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
|||
|
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
|||
|
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
|||
|
<a class="dropdown-item" href="Extended9Blockchain.html"> 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"> A.1. C Language Reintroduction</a>
|
|||
|
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
|||
|
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
|||
|
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
|||
|
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
|||
|
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
|||
|
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
|||
|
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
|||
|
<a class="dropdown-item" href="Files.html"> 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">
|
|||
|
«  <a id="prevmod" href="POSIXvSysV.html">3.5. POSIX vs. System V IPC</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod" href="ShMem.html">3.7. Shared Memory</a>  »
|
|||
|
|
|||
|
</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 – <mqueue.h></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 "HELLO" 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">"/OpenCSF_MQ"</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">"mq_open"</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 "HELLO" as a message with priority 10, then close the queue.</span>
|
|||
|
<span class="cm"> Note the size is 6 to include the null byte '\0'. */</span>
|
|||
|
<span class="n">mq_send</span> <span class="p">(</span><span class="n">mqd</span><span class="p">,</span> <span class="s">"HELLO"</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">"/OpenCSF_MQ"</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">&</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">&</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">"Failed to receive message</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
|||
|
<span class="k">else</span>
|
|||
|
<span class="nf">printf</span> <span class="p">(</span><span class="s">"Received [priority %u]: '%s'</span><span class="se">\n</span><span class="s">"</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">&</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 queue’s
|
|||
|
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">'q'</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">&</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">&</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 – <mqueue.h></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&localMode=true&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">
|
|||
|
«  <a id="prevmod1" href="POSIXvSysV.html">3.5. POSIX vs. System V IPC</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod1" href="ShMem.html">3.7. Shared Memory</a>  »
|
|||
|
</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>
|