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

558 lines
No EOL
43 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.8. Semaphores &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="9. Extended Example: Bash-lite: A Simple Command-line Shell" href="Extended3Bash.html" />
<link rel="prev" title="7. Shared Memory" href="ShMem.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="IPCSems.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="IPCSems.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/IPCSems.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="ShMem.html">3.7. Shared Memory</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="Extended3Bash.html">3.9. Extended Example: Bash-lite: A Simple Command-line Shell</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 = "IPCSems";ODSA.SETTINGS.MODULE_LONG_NAME = "Semaphores";ODSA.SETTINGS.MODULE_CHAPTER = "Concurrency with IPC"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:50"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="semaphores">
<h1>3.8. Semaphores<a class="headerlink" href="IPCSems.html#semaphores" title="Permalink to this headline"></a></h1>
<p><a class="reference internal" href="Glossary.html#term-semaphore"><span class="xref std std-term">Semaphores</span></a> are different from the other forms of IPC discussed in this chapter,
because they do not allow for the general exchange of data. That is, you cannot use a semaphore to
transmit application-specific information from one process to another. Rather, semaphores are used
to synchronize access to shared resources; that is, semaphores <strong>control the timing of shared
accesses that may conflict</strong>.</p>
<p>As a preliminary example, consider a multi-process database application that handles banking
information. Assume that one process is accessing the file for your account to record a deposit that
youve made. While this is happening, another process also opens your account file to record a
purchase. You want to make sure that the transaction for the deposit is completely recorded before
money is removed from your account. That is, you want the application to control the timing of these
events.</p>
<p><a class="reference internal" href="Glossary.html#term-synchronization"><span class="xref std std-term">Synchronization</span></a> is a complex topic that will be covered in its own chapter. In this section,
we will start with the simplest case of synchronization with semaphores: <a class="reference internal" href="Glossary.html#term-signaling-synchronization"><span class="xref std std-term">signaling</span></a> to
another process that an action has been performed. This concept is very similar to the signals used
to control the life cycle of a process (e.g., <code class="docutils literal notranslate"><span class="pre">SIGKILL</span></code>). The form of signaling that we are now
discussing is more generic and allows applications to define their own custom events. That is,
semaphores let processes inform other processes that <cite>something</cite> has happened, and that something is
a custom event that only matters to that application. This type of signaling can be considered to
follow the message passing IPC model, as each signal sent requires a system call.</p>
<p>Fundamentally, a semaphore is a non-negative integer <a class="footnote-reference" href="IPCSems.html#f19" id="id1">[1]</a> with two operations: incrementing or
decrementing the value by 1. For a variety of reasons, these two operations have many different
names that can be used interchangeably. Incrementing a semaphore is also called <em>upping</em>,
<em>signaling</em>, <em>posting</em>, and <em>V</em> (from the Dutch word <cite>verhogen</cite>, “to raise”). Decrementing a
semaphore is also called <em>downing</em>, <em>waiting</em>, or <em>P</em> (from the Dutch <cite>proberen</cite>, “to test”). <a class="footnote-reference" href="IPCSems.html#f20" id="id2">[2]</a></p>
<p>The key behavior is that any process that attempting to decrement a semaphore whose current value is
0 will become blocked until another process increments the value. If the current value is greater
than 0 when a process decrements the value, the process can continue processing without waiting.
When using semaphores, a simple heuristic to consider for the initial value is to ask how many
processes should be given immediate access. Specifically, the initial value determines how many
decrements can occur (without any corresponding increments) before processes start to get blocked.
If a semaphore is initialized to 1, a single process can decrement the semaphore without waiting; a
second process would be blocked. Initializing the semaphore to 10 would allow 10 processes through.
This topic will be discussed in more detail in Chapters 8 and 9.</p>
<p>To illustrate the basic signaling pattern described above, consider two processes (call them A and
B) that have access to a shared memory region. Assume that A is writing data to the region and B
needs to know when the writing is completed. (For simplicity, this scenario is a one-time data
exchange. Once A is finished writing, it will not write again.) To make the signaling happen, A and
B share access to a semaphore initialized to 0. A will increment the semaphore after it has
completed writing the data and B will decrement the semaphore before it attempts to read. Observe
the timings that are possible with this sequence of events:</p>
<blockquote>
<div><ul class="simple">
<li>In one ordering, B attempts to decrement the semaphore before A has completed writing. Since the
semaphores value is 0, B becomes blocked and must wait until A finishes. A eventually completes
the write and increments the semaphore, unblocking B.</li>
<li>In a different ordering, A finishes writing and increments the semaphore before B tries to read.
When B later goes to read the data, the semaphores value will be 1 (because A already incremented
the value) and it can continue without blocking.</li>
</ul>
</div></blockquote>
<p>In either order, the semaphore guarantees that B cannot read any data until A has completed writing
to the shared memory.</p>
<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 the scenario above, it is important to initialize the semaphore to 0 to achieve the proper
timing. A common mistake here would be to initialize the semaphore to 1, thinking that we only want
one of the two processes to access the shared memory. This practice is known as <a class="reference internal" href="Glossary.html#term-mutual-exclusion"><span class="xref std std-term">mutual
exclusion</span></a>, and will be discussed as an important synchronization pattern. The problem in this
scenario is that mutual exclusion does not ensure the proper timing. Specifically, if the semaphore
is initialized to 1 and B decrements the semaphore first, A will be blocked. Consequently, A cannot
even begin writing to the shared memory and both processes will end up waiting indefinitely.</p>
</div>
<div class="section" id="posix-vs-system-v-semaphores">
<h2>3.8.1. POSIX vs. System V Semaphores<a class="headerlink" href="IPCSems.html#posix-vs-system-v-semaphores" title="Permalink to this headline"></a></h2>
<p><a class="reference internal" href="Glossary.html#term-semaphore"><span class="xref std std-term">Semaphores</span></a>, like message queues and shared memory, have both a POSIX and System
V interface specification. Key differences between the two versions of semaphores include the following:</p>
<blockquote>
<div><ul class="simple">
<li>POSIX semaphores are created and initialized in a single operation, one at a time. System V
semaphores are created as a set, and each semaphore can be initialized independently later.</li>
<li>POSIX semaphores can only be incremented or decremented by 1. System V semaphore operations allow
processes to specify any unsigned integer that will be added to the semaphores value immediately.</li>
<li>POSIX semaphores provide non-blocking operations that try to decrement the value. If the value is
currently 0 (which would block the process), the attempt will fail and the process can react in
other ways. System V semaphores do not provide this feature.</li>
<li>System V semaphores are identified by <code class="docutils literal notranslate"><span class="pre">key_t</span></code> values. POSIX semaphores can be identified by valid
POSIX names (begin with a “<code class="docutils literal notranslate"><span class="pre">/</span></code>”) or they can be unnamed.</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="posix-named-semaphores">
<h2>3.8.2. POSIX Named Semaphores<a class="headerlink" href="IPCSems.html#posix-named-semaphores" title="Permalink to this headline"></a></h2>
<p>POSIX defines two types of semaphores: named and unnamed. <a class="reference internal" href="Glossary.html#term-named-semaphore"><span class="xref std std-term">Named semaphores</span></a>
are created using the standard POSIX arguments of <code class="docutils literal notranslate"><span class="pre">name</span></code>, <code class="docutils literal notranslate"><span class="pre">oflag</span></code>, and <code class="docutils literal notranslate"><span class="pre">mode</span></code>, along with an
initial unsigned integer <code class="docutils literal notranslate"><span class="pre">value</span></code>. The <code class="docutils literal notranslate"><span class="pre">mode</span></code> and <code class="docutils literal notranslate"><span class="pre">value</span></code> parameters must both be included when
creating a new semaphore, and both must be excluded when connecting to an existing semaphore. The
<code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> and <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> functions decrement (wait) or increment (post) the semaphores
value. If the value is currently 0, <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> will block the current process until the value is
changed by another process calling <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code>. Note that <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> will only unblock one
process at a time; if five processes are waiting on the semaphore, then five calls to <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code>
must be made to unblock them all.</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;semaphore.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">sem_t</span> <span class="pre">*sem_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>&#160; <span class="pre">/*</span> <span class="pre">mode_t</span> <span class="pre">mode,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">value</span> <span class="pre">*/</span> <span class="pre">);</span></code></dt>
<dd>Returns (and optionally creates) a named semaphore.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_wait</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Decrement the semaphores value; block if the value is currently 0.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_post</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Increment the semaphores value; resume another process if the value is 0.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_close</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Close a semaphore.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_unlink</span> <span class="pre">(const</span> <span class="pre">char</span> <span class="pre">*name);</span></code></dt>
<dd>Delete a named semaphore.</dd>
</dl>
</div>
<p><a class="reference external" href="IPCSems.html#cl3-11">Code Listing 3.11</a> illustrates how semaphores can be used to control the timing of two processes. In
this example, the semaphore is used to guarantee the messages are printed in the correct order
(“first” then “second” then “third”). Specifically, the semaphore blocks the child process until the
parent prints “first” and ups the semaphore; then the parent calls <code class="docutils literal notranslate"><span class="pre">wait()</span></code>, which forces it to
wait until the child exits. It is important to emphasize that named semaphores can be used by
unrelated processes; they do not have to be parent and child as used in this example.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-11"><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
27
28
29
30
31
32</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.11:</span>
<span class="cm"> Creating and using a POSIX semaphore to control the timing of parent/child execution</span>
<span class="cm"> */</span>
<span class="cm">/* Create and open the semaphore */</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">sem</span> <span class="o">=</span> <span class="n">sem_open</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_Sema&quot;</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_EXCL</span><span class="p">,</span> <span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">sem</span> <span class="o">!=</span> <span class="n">SEM_FAILED</span><span class="p">);</span>
<span class="cm">/* Fork to create the child process */</span>
<span class="kt">pid_t</span> <span class="n">child_pid</span> <span class="o">=</span> <span class="n">fork</span><span class="p">();</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">child_pid</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="cm">/* Note the child inherits a copy of the semaphore connection */</span>
<span class="cm">/* Child process: wait for semaphore, print &quot;second&quot;, then exit */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">child_pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">sem</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;second</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">sem_close</span> <span class="p">(</span><span class="n">sem</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Parent prints then posts to the semaphore and waits on child */</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;first</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">sem</span><span class="p">);</span>
<span class="n">wait</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Now the child has printed and exited */</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;third</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">sem_close</span> <span class="p">(</span><span class="n">sem</span><span class="p">);</span>
<span class="n">sem_unlink</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_Sema&quot;</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>In many circumstances, a process may wish to check on the status of a semaphore without getting
blocked indefinitely. For instance, assume one process is using a semaphore to signal that it has
completed some important task; another process may want to check on whether the task has been
completed, but still continue processing even if the event has not happened yet. Downing the
semaphore with <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> would not work, because it would block the process until the event
occurs. Instead, POSIX provides two alternative functions for waiting on a semaphore. With
<code class="docutils literal notranslate"><span class="pre">sem_trywait()</span></code>, a process can try to down the semaphore; however, if the semaphores current
value is 0, then <code class="docutils literal notranslate"><span class="pre">sem_trywait()</span></code> returns an error instead of blocking. Alternatively,
<code class="docutils literal notranslate"><span class="pre">sem_timedwait()</span></code> allows the process to specify a maximum amount of time to block; if no post
occurs before the timeout arrives, then the process is unblocked and an error is returned.</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;semaphore.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_trywait</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Try to decrement the semaphore; return an error if doing so would block</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_timedwait</span> <span class="pre">(sem_t</span> <span class="pre">*sem,</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>Decrement the semaphore, but place a time limit on the blocking</dd>
</dl>
</div>
</div>
<div class="section" id="posix-unnamed-semaphores">
<h2>3.8.3. POSIX Unnamed Semaphores<a class="headerlink" href="IPCSems.html#posix-unnamed-semaphores" title="Permalink to this headline"></a></h2>
<p>POSIX <a class="reference internal" href="Glossary.html#term-unnamed-semaphore"><span class="xref std std-term">unnamed semaphores</span></a> provide a lightweight approach for creating and
using semaphores. Specifically, where <code class="docutils literal notranslate"><span class="pre">sem_open()</span></code> returns a pointer to a newly allocated
semaphore, <code class="docutils literal notranslate"><span class="pre">sem_init()</span></code> takes a reference to a semaphore variable (declared as a <code class="docutils literal notranslate"><span class="pre">sem_t</span></code>) that
has already been allocated within the current processs memory space and sets the semaphore to the
value passed. Once the semaphore is initialized, the other functions specified for named semaphores
(e.g., <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> and <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code>) can be used.</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;semaphore.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_init</span> <span class="pre">(sem_t</span> <span class="pre">*sem,</span> <span class="pre">int</span> <span class="pre">pshared,</span> <span class="pre">unsigned</span> <span class="pre">int</span> <span class="pre">value);</span></code></dt>
<dd>Create and initialize a POSIX unnamed semaphore.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_destroy</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Delete a POSIX unnamed semaphore.</dd>
</dl>
</div>
<p>POSIX unnamed semaphores have one very important difference from named semaphores: <strong>unnamed
semaphores must exist in shared memory</strong>. That is, the preceding code example would not work with
unnamed semaphores, because the parent and child processes have distinct memory spaces. As such, the
<code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> and <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> calls in that code are meaningless, because they are operating on
two different semaphores. However, if a shared memory space were set up with <code class="docutils literal notranslate"><span class="pre">shmat()</span></code>, the
semaphore could be stored within that region and the code would work.</p>
<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>macOS provides POSIX named semaphores, but <strong>it does not support unnamed semaphores</strong>. macOS
programs written with unnamed semaphores <cite>will</cite> (unfortunately) compile, but the program will not
behave correctly. The <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> function will return an error and will not block the process.
As noted previously, applications targeting macOS should generally use the System V IPC interface
rather than POSIX.</p>
</div>
<p>The shared memory requirement for POSIX unnamed semaphores limits their usefulness in terms of IPC.
They are much more commonly used with <a class="reference internal" href="Glossary.html#term-multithreading"><span class="xref std std-term">multithreaded programs</span></a>, since
multiple threads in the same process automatically share the same memory space. Using unnamed
semaphores in that case reduces the kernel system overhead, as the semaphore is stored within the
process itself.</p>
<p>One scenario where POSIX unnamed semaphores are very helpful for IPC arises when creating a complex
shared data structure. For instance, consider a binary search tree consisting of millions of nodes
that is stored in a shared memory region. If the application needs to associate a distinct semaphore
with each node, assigning and keeping track of millions of names would be a horrifying burden.
Instead, each nodes <code class="docutils literal notranslate"><span class="pre">struct</span></code> declaration could include a <code class="docutils literal notranslate"><span class="pre">sem_t</span></code> field. This approach would
simplify the management of the data structure, allowing each semaphore to be created or destroyed
automatically with the tree node.</p>
<table class="docutils footnote" frame="void" id="f19" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="IPCSems.html#id1">[1]</a></td><td>This section is describing the typical implementation of semaphores in most modern OS. The
original definition of semaphores allowed the values to be negative, too. In the original version,
decrementing the semaphore would first subtract one from the current value, then check if the
result was negative; if so, the process would block. In modern implementations, the value is
checked first; if the current value is zero, the process blocks and the subtraction does not occur
until later. The difference in behavior has very subtle implications that go beyond the scope of
this book. For our purposes, either implementation will work sufficiently.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="f20" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="IPCSems.html#id2">[2]</a></td><td><code class="docutils literal notranslate"><span class="pre">P()</span></code> and <code class="docutils literal notranslate"><span class="pre">V()</span></code> were the original names for the semaphore operations. Semaphores were
proposed by the Dutch computer scientist, Edsger Dijkstra. These names are never used in modern
systems, but they are included here for historical reference. Our general preference is to use
decrement/increment, given that this pair clearly indicate how the value changes. We also use
wait/post, however, in relation to POSIX semaphores to match the functions (<code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> and
<code class="docutils literal notranslate"><span class="pre">sem_post()</span></code>) as named in the interface.</td></tr>
</tbody>
</table>
<div
id="IPCSemSumm"
class="embedContainer"
data-exer-name="IPCSemSumm"
data-long-name="IPC semaphore questions"
data-short-name="IPCSemSumm"
data-frame-src="../../../Exercises/IPC/IPCSemSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=IPCSems&amp;JXOP-debug=true&amp;JOP-lang=en&amp;JXOP-code=java"
data-frame-width="950"
data-frame-height="550"
data-external="false"
data-points="1.0"
data-required="True"
data-showhide="show"
data-threshold="2"
data-type="ka"
data-exer-id="">
<div class="center">
<div id="IPCSemSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="ShMem.html">3.7. Shared Memory</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="Extended3Bash.html">3.9. Extended Example: Bash-lite: A Simple Command-line Shell</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>