891 lines
No EOL
66 KiB
HTML
891 lines
No EOL
66 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
|
||
|
||
|
||
<html lang="en">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
||
<title>3.3. Pipes and FIFOs — 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="4. Shared Memory With Memory-mapped Files" href="MMap.html" />
|
||
<link rel="prev" title="2. IPC Models" href="IPCModels.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="Pipes.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="Pipes.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/Pipes.rst"
|
||
target="_blank" rel="nofollow">Show Source</a></li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
|
||
<div class="container center">
|
||
«  <a id="prevmod" href="IPCModels.html">3.2. IPC Models</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod" href="MMap.html">3.4. Shared Memory With Memory-mapped Files</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 = "Pipes";ODSA.SETTINGS.MODULE_LONG_NAME = "Pipes and FIFOs";ODSA.SETTINGS.MODULE_CHAPTER = "Concurrency with IPC"; ODSA.SETTINGS.BUILD_DATE = "2021-06-30 17:11:35"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="pipes-and-fifos">
|
||
<h1>3.3. Pipes and FIFOs<a class="headerlink" href="Pipes.html#pipes-and-fifos" title="Permalink to this headline">¶</a></h1>
|
||
<p><a class="reference internal" href="Glossary.html#term-pipe"><span class="xref std std-term">Pipes</span></a> allow processes to communicate using a unidirectional byte stream, with two
|
||
ends designated by distinct <a class="reference internal" href="Glossary.html#term-file-descriptor"><span class="xref std std-term">file descriptors</span></a>. A common visual analogy for
|
||
a pipe is a real-world water pipe; water that is poured into one end of the pipe comes out the other
|
||
end. In the case of IPC, the “water” is the sequence of bytes being sent between the processes; the
|
||
bytes are written into one end of the pipe and read from the other end. Pipes have several important
|
||
characteristics that shape their use:</p>
|
||
<blockquote>
|
||
<div><ul class="simple">
|
||
<li>Pipes are <em>unidirectional</em>; one end must be designated as the reading end and the other as
|
||
the writing end. Note that there is no restriction that different processes must read from and
|
||
write to the pipe; rather, if one process writes to a pipe then immediately reads from it, the
|
||
process will receive its own message. If two processes need to exchange messages back and forth,
|
||
they should use two pipes.</li>
|
||
<li>Pipes are <em>order preserving</em>; all data read from the receiving end of the pipe will match
|
||
the order in which it was written into the pipe. There is no way to designate some data as higher
|
||
priority to ensure it is read first.</li>
|
||
<li>Pipes have a <em>limited capacity</em> and they use <a class="reference internal" href="Glossary.html#term-blocking-i-o"><span class="xref std std-term">blocking I/O</span></a>; if a pipe is full, any
|
||
additional writes to the pipe will block the process until some of the data has been read. As such,
|
||
there is no concern that the messages will be dropped, but there may be performance delays, as the
|
||
writing process has no control over when the bytes will be removed from the pipe.</li>
|
||
<li>Pipes send data as unstructured <em>byte streams</em>. There are no pre-defined
|
||
characteristics to the data exchanged, such as a predictable message length. The processes using
|
||
the pipe must agree on a communication protocol and handle errors appropriately (such as if one of
|
||
the processes terminates the communication early).</li>
|
||
<li>Messages that are smaller than the size specified by <code class="docutils literal notranslate"><span class="pre">PIPE_BUF</span></code> are guaranteed to be sent
|
||
<a class="reference internal" href="Glossary.html#term-atomic"><span class="xref std std-term">atomically</span></a>. As such, if two processes write to a pipe at the same time, both
|
||
messages will be written correctly and they will not interfere with each other.</li>
|
||
</ul>
|
||
</div></blockquote>
|
||
<div class="section" id="basic-pipes">
|
||
<h2>3.3.1. Basic Pipes<a class="headerlink" href="Pipes.html#basic-pipes" title="Permalink to this headline">¶</a></h2>
|
||
<p>The simplest form of communication with pipes is to provide parent-child communication using the
|
||
<code class="docutils literal notranslate"><span class="pre">pipe()</span></code> library function. This function takes an int array of length 2. (Recall that arrays are
|
||
always passed by reference.) Assuming the kernel is able to create the pipe, the array will contain
|
||
the file descriptors for the two ends of the pipe. If the pipe creation, the function returns -1.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int pipe (int pipefd[2]);</span></code></dt>
|
||
<dd>Opens a pipe and returns the file descriptors in the array.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>Once the pipe is opened, we can use the standard <code class="docutils literal notranslate"><span class="pre">read()</span></code> and <code class="docutils literal notranslate"><span class="pre">write()</span></code> functions with the file
|
||
descriptors. <a class="reference external" href="Pipes.html#cl3-1">Code Listing 3.1</a> show the standard convention of using the array index 1 for writing
|
||
and 0 for reading. This practice aligns with the use of file descriptor 1 for <code class="docutils literal notranslate"><span class="pre">stdout</span></code> and 0 for <code class="docutils literal notranslate"><span class="pre">stdin</span></code>.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-1"><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
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.1:</span>
|
||
<span class="cm"> Sending a simple message through a pipe to a child process</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="kt">int</span> <span class="n">pipefd</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
|
||
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span>
|
||
<span class="cm">/* Clear the buffer */</span>
|
||
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
|
||
<span class="cm">/* Open the pipe */</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">pipe</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">)</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"ERROR: Failed to open pipe</span><span class="se">\n</span><span class="s">"</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">/* Create a 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="mi">0</span><span class="p">);</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="cm">/* Child closes write-end, then reads from the pipe */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
<span class="kt">ssize_t</span> <span class="n">bytes_read</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">bytes_read</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Child received: '%s'</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="cm">/* Parent closes the unused reading end */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
|
||
<span class="cm">/* Parent sends 'hello' and waits */</span>
|
||
<span class="n">strncpy</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">"hello"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Parent is sending '%s'</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
|
||
<span class="n">write</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</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="n">printf</span> <span class="p">(</span><span class="s">"Child should have printed the message</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>This code illustrates several conventions with using pipes. First, for the parent and child to
|
||
communicate, <code class="docutils literal notranslate"><span class="pre">pipe()</span></code> must be called before <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. This ordering is required to give both
|
||
processes access to the pipe. Second, it is customary for each process to close one end of the pipe
|
||
immediately after the <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. This practice helps to align the unidirectional nature of the pipe
|
||
with its intended use. That is, the convention is that a pipe is reserved for sending data from one
|
||
process to another; if the second process wants to respond, it should use a different pipe. Third,
|
||
the file descriptor at index 1 is used for writing, while index 0 is for reading.</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>It is very important to follow the convention of closing the unused end of the pipe
|
||
immediately after the <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. Failure to do so can cause programs to freeze
|
||
unexpectedly. Consider the following example:</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
|
||
6
|
||
7
|
||
8</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="kt">int</span> <span class="n">pipefd</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
|
||
<span class="n">pipe</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">);</span>
|
||
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">fork</span> <span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="cm">/* child exits without writing */</span>
|
||
|
||
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span>
|
||
<span class="n">read</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>On line 8, the parent process will try to read from the pipe. Instead of immediately
|
||
returning, the process will block until an <code class="docutils literal notranslate"><span class="pre">EOF</span></code> (end-of-file) is written into the pipe.
|
||
Since the child is the only other process that could write to the pipe and the child
|
||
exits without writing anything, the parent will block indefinitely. This problem can
|
||
be difficult to diagnose, such as when the child process is redirecting the standard
|
||
output of an external program using <code class="docutils literal notranslate"><span class="pre">dup2()</span></code> (which we illustrate below) and the
|
||
external program produces no output. To avoid this frustration, always close the
|
||
unused end of the pipe.</p>
|
||
</div>
|
||
<div class="figure mb-2 align-center" id="id1">
|
||
<span id="ipcpipe"></span><a class="reference internal image-reference" href="_images/CSF-Images.3.1.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Pipes are unidirectional and should not be used to respond" src="_images/CSF-Images.3.1.png" style="width: 80%;" /></a>
|
||
<p class="caption align-center px-3"><span class="caption-text"> Figure 3.3.3: Pipes are unidirectional and should not be used to respond</span></p>
|
||
</div>
|
||
<p><a href="Pipes.html#ipcpipe">Figure 3.3.3</a> illustrates a key feature and common bug with pipes. Once a process
|
||
has used <code class="docutils literal notranslate"><span class="pre">pipefd[0]</span></code> in a call to <code class="docutils literal notranslate"><span class="pre">read()</span></code>, the same process cannot turn around and <code class="docutils literal notranslate"><span class="pre">write()</span></code>
|
||
to <code class="docutils literal notranslate"><span class="pre">pipefd[1]</span></code>; doing so will fail silently and no data will be sent. To allow for bidirectional
|
||
communication, use two pipes as in <a class="reference external" href="Pipes.html#cl3-2">Code Listing 3.2</a>. After performing the <code class="docutils literal notranslate"><span class="pre">fork()</span></code>, either pipe
|
||
can be designated to be used for parent-to-child or child-to-parent messages.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-2"><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
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40
|
||
41
|
||
42
|
||
43
|
||
44
|
||
45
|
||
46
|
||
47
|
||
48
|
||
49
|
||
50
|
||
51</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.2:</span>
|
||
<span class="cm"> Using two pipes for bidirectional communication between parent and child</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="kt">int</span> <span class="n">p2cfd</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span> <span class="cm">/* parent-to-child */</span>
|
||
<span class="kt">int</span> <span class="n">c2pfd</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span> <span class="cm">/* child-to-parent */</span>
|
||
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span>
|
||
<span class="kt">ssize_t</span> <span class="n">bytes_read</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||
|
||
<span class="cm">/* Clear the buffer and open the pipe */</span>
|
||
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
<span class="k">if</span> <span class="p">((</span><span class="n">pipe</span> <span class="p">(</span><span class="n">p2cfd</span><span class="p">)</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">pipe</span> <span class="p">(</span><span class="n">c2pfd</span><span class="p">)</span> <span class="o"><</span> <span class="mi">0</span><span class="p">))</span>
|
||
<span class="p">{</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"ERROR: Failed to open pipe</span><span class="se">\n</span><span class="s">"</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">/* Create a 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="mi">0</span><span class="p">);</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="cm">/* Child closes write end of p2c, read of c2p */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">p2cfd</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">c2pfd</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
<span class="n">bytes_read</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">p2cfd</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">bytes_read</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Child received: '%s'</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Child sends response of "goodbye" */</span>
|
||
<span class="n">strncpy</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">"goodbye"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
<span class="n">write</span> <span class="p">(</span><span class="n">c2pfd</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="cm">/* Parent closes read end of p2c, write of c2p */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">p2cfd</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">c2pfd</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
|
||
<span class="cm">/* Parent sends 'hello' and waits */</span>
|
||
<span class="n">strncpy</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">"hello"</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Parent is sending '%s'</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
|
||
<span class="n">write</span> <span class="p">(</span><span class="n">p2cfd</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
|
||
<span class="cm">/* Parent reads response back from child */</span>
|
||
<span class="n">bytes_read</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">c2pfd</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">bytes_read</span> <span class="o"><=</span> <span class="mi">0</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="cm">/* should receive response */</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Parent received: '%s'</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p><a href="Pipes.html#ipctwopipe">Figure 3.3.4</a> illustrates the circular structure of the two pipes used in Code
|
||
Listing 3.2. The parent uses <code class="docutils literal notranslate"><span class="pre">p2cfd</span></code> to send data to the child. Responses from the child use the
|
||
other pipe, identified by <code class="docutils literal notranslate"><span class="pre">c2pfd</span></code>. In both cases, the calls to <code class="docutils literal notranslate"><span class="pre">write()</span></code> use index 1 and the
|
||
<code class="docutils literal notranslate"><span class="pre">read()</span></code> calls use index 0.</p>
|
||
<div class="figure mb-2 align-center" id="id2">
|
||
<span id="ipctwopipe"></span><a class="reference internal image-reference" href="_images/CSF-Images.3.2.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Structure of the two pipes used in Code Listing 3.2" src="_images/CSF-Images.3.2.png" style="width: 80%;" /></a>
|
||
<p class="caption align-center px-3"><span class="caption-text"> Figure 3.3.4: Structure of the two pipes used in Code Listing 3.2</span></p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="pipes-and-shell-commands">
|
||
<h2>3.3.2. Pipes and Shell Commands<a class="headerlink" href="Pipes.html#pipes-and-shell-commands" title="Permalink to this headline">¶</a></h2>
|
||
<p>One of the most common use of pipes is to link together multiple commands on the command line. For
|
||
instance, consider the following command line:</p>
|
||
<div class="highlight-none border border-dark rounded-lg bg-light px-2 mb-3 notranslate"><div class="highlight bg-light"><pre class="mb-0"><span></span>$ ls -l | sort -n -k 5 | tail -n 1 | awk '{print $NF}'
|
||
</pre></div>
|
||
</div>
|
||
<p>This command line creates four processes that are linked together. First, the <code class="docutils literal notranslate"><span class="pre">ls</span></code> command prints
|
||
out the list of files along with their details. This list is sent as input to <code class="docutils literal notranslate"><span class="pre">sort</span></code>, which sorts
|
||
numerically based on the 5th field (the file size). The <code class="docutils literal notranslate"><span class="pre">tail</span></code> process then grabs the last line,
|
||
which is the line for the largest file. Finally, <code class="docutils literal notranslate"><span class="pre">awk</span></code> will print the last field of that line,
|
||
which is the file name of whatever file is the largest.</p>
|
||
<div class="figure mb-2 align-center" id="id3">
|
||
<span id="ipcpipeline"></span><a class="reference internal image-reference" href="_images/CSF-Images.3.3.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Chained logical structure of a sequence of bash commands connected with pipes" src="_images/CSF-Images.3.3.png" style="width: 80%;" /></a>
|
||
<p class="caption align-center px-3"><span class="caption-text"> Figure 3.3.5: Chained logical structure of a sequence of bash commands connected with pipes</span></p>
|
||
</div>
|
||
<p><a href="Pipes.html#ipcpipeline">Figure 3.3.5</a> illustrates the chained structure of these four processes. These
|
||
four processes are created by bash using both <code class="docutils literal notranslate"><span class="pre">fork()</span></code> and <code class="docutils literal notranslate"><span class="pre">exec()</span></code>. Once the processes are
|
||
created, <code class="docutils literal notranslate"><span class="pre">bash</span></code> links their standard input and output by setting up a pipe to connect each process
|
||
with the one after it. (This is the reason the vertical bar (<code class="docutils literal notranslate"><span class="pre">|</span></code>) is referred to as a pipe.)
|
||
However, there is an additional step: <code class="docutils literal notranslate"><span class="pre">bash</span></code> needs to link the pipe with each process’s standard
|
||
input and output. The <code class="docutils literal notranslate"><span class="pre">dup2()</span></code> function accomplishes this task.</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 – <unistd.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int dup2 (int oldfd, int newfd);</span></code></dt>
|
||
<dd>Closes newfd and replaces it with the file of oldfd</dd>
|
||
</dl>
|
||
</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>The arguments for <code class="docutils literal notranslate"><span class="pre">dup2()</span></code> are easily confused because of the names given in the standard C
|
||
documentation. The <code class="docutils literal notranslate"><span class="pre">newfd</span></code> is the file descriptor that you want to use after the call to
|
||
<code class="docutils literal notranslate"><span class="pre">dup2()</span></code>. For instance, if you want to change your file descriptors so that subsequent calls to
|
||
<code class="docutils literal notranslate"><span class="pre">printf()</span></code> write to the pipe instead of the standard output screen, the <code class="docutils literal notranslate"><span class="pre">newfd</span></code> argument should
|
||
be <code class="docutils literal notranslate"><span class="pre">STDOUT_FILENO</span></code>. (The confusion seems to arise because the pipe was created after standard
|
||
output, so new programmers often think of the pipe file descriptor as “new,” which is incorrect.)</p>
|
||
</div>
|
||
<p><a class="reference external" href="Pipes.html#cl3-3">Code Listing 3.3</a> illustrates the basic functionality of how <code class="docutils literal notranslate"><span class="pre">bash</span></code> uses <code class="docutils literal notranslate"><span class="pre">dup2()</span></code> with pipes to
|
||
link commands together. Specifically, the command line would be <code class="docutils literal notranslate"><span class="pre">ls</span> <span class="pre">|</span> <span class="pre">sort</span></code>, so <code class="docutils literal notranslate"><span class="pre">bash</span></code> needs to
|
||
create and link two processes. The <code class="docutils literal notranslate"><span class="pre">sort</span></code> process closes the write end of the pipe and links the
|
||
read end to become its standard input.</p>
|
||
<p>Similarly, the <code class="docutils literal notranslate"><span class="pre">ls</span></code> process closes its read end of the pipe and links the write end to its
|
||
standard output. Anything that <code class="docutils literal notranslate"><span class="pre">ls</span></code> writes to its standard output (using <code class="docutils literal notranslate"><span class="pre">printf()</span></code>), <code class="docutils literal notranslate"><span class="pre">sort</span></code>
|
||
would read from its standard input; both processes are unaware that the pipe exists. In fact, even
|
||
if this code used <code class="docutils literal notranslate"><span class="pre">exec()</span></code> to load new program code within these child processes, the processes
|
||
would continue to use the pipe as <code class="docutils literal notranslate"><span class="pre">stdin</span></code> and <code class="docutils literal notranslate"><span class="pre">stdout</span></code> without any change to the program’s source code.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-3"><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
|
||
33
|
||
34
|
||
35
|
||
36
|
||
37
|
||
38
|
||
39
|
||
40
|
||
41
|
||
42
|
||
43
|
||
44</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.3:</span>
|
||
<span class="cm"> Creating a bash-like linkage between two processes</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Parent is acting like 'bash' interpreting the command line:</span>
|
||
<span class="cm"> $ ls | sort</span>
|
||
<span class="cm"> This example assumes the variable declaration and pipe creation</span>
|
||
<span class="cm"> as shown in Code Listing 3.1. */</span>
|
||
|
||
<span class="cm">/* 'sort' child process */</span>
|
||
<span class="n">assert</span> <span class="p">((</span><span class="n">child_pid</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">())</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">child_pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="cm">/* 'sort' closes unused write end of the pipe */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
<span class="cm">/* ...and uses the read end as standard input */</span>
|
||
<span class="n">dup2</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">STDIN_FILENO</span><span class="p">);</span>
|
||
<span class="cm">/* Reading from "stdin" now reads from the pipe */</span>
|
||
<span class="kt">ssize_t</span> <span class="n">bytes_read</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">STDIN_FILENO</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">bytes_read</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="cm">/* Trim off the trailing newline character */</span>
|
||
<span class="kt">char</span> <span class="o">*</span><span class="n">token</span> <span class="o">=</span> <span class="n">strtok</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"'sort' process received '%s'</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">token</span><span class="p">);</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="cm">/* 'ls' child process */</span>
|
||
<span class="n">assert</span> <span class="p">((</span><span class="n">child_pid</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">())</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">child_pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="cm">/* 'ls' closes the read end of the pipe */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
<span class="cm">/* ...and uses the write end as standard output */</span>
|
||
<span class="n">dup2</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">STDOUT_FILENO</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* printf() now writes to the pipe instead of the screen */</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"list of files</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="n">exit</span> <span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
<span class="cm">/* 'bash' parent closes both ends of the pipe within itself */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">pipefd</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
|
||
<span class="n">wait</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>This example also illustrates one subtle aspect of the closing of pipes. When a process closes one
|
||
end of the pipe, it is only closing <cite>its access</cite> to that end of the pipe. Other processes may still
|
||
use that end of the pipe. For instance, in the previous example, observe that the parent process
|
||
closes both <code class="docutils literal notranslate"><span class="pre">pipefd[0]</span></code> and <code class="docutils literal notranslate"><span class="pre">pipefd[1]</span></code>. This does not affect the pipe itself, and it does not
|
||
prevent the two child processes from communicating via the pipe. All these two lines of code do are
|
||
close the parent’s (<code class="docutils literal notranslate"><span class="pre">bash</span></code>’s) access to the pipe, preventing it from reading or writing to the
|
||
pipe. The pipe will remain in existence until all processes with access either close both ends of
|
||
the pipe or exit (which closes all open file connections).</p>
|
||
</div>
|
||
<div class="section" id="fifos">
|
||
<h2>3.3.3. FIFOs<a class="headerlink" href="Pipes.html#fifos" title="Permalink to this headline">¶</a></h2>
|
||
<p>The pipes described above create a simple mechanism for parent and child processes to communicate,
|
||
but they cannot be used for unrelated processes. Specifically, notice that the call to <code class="docutils literal notranslate"><span class="pre">pipe()</span></code>
|
||
must happen within the same program that later calls <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. That is, the pipe is first created
|
||
within a single process and is only shared with processes created as children (or children of
|
||
children, if the child also calls <code class="docutils literal notranslate"><span class="pre">fork()</span></code>). This approach will not work for two random processes
|
||
that need to create an ad hoc communication session. <a class="reference internal" href="Glossary.html#term-fifo"><span class="xref std std-term">FIFOs</span></a> (first-in, first-out)
|
||
are a variation on a pipe that creates a more flexible communication structure.</p>
|
||
<p>FIFOs work by attaching a filename to the pipe. For this reason, FIFOs are also called <a class="reference internal" href="Glossary.html#term-named-pipe"><span class="xref std std-term">named pipes</span></a>
|
||
as opposed to the anonymous pipes discussed previously. FIFOs are created by one process that
|
||
calls <code class="docutils literal notranslate"><span class="pre">mkfifo()</span></code>. Once created, any process (with correct access permissions) can access the FIFO
|
||
by calling <code class="docutils literal notranslate"><span class="pre">open()</span></code> on the associated filename. Once the processes have opened the file, they can
|
||
use the standard <code class="docutils literal notranslate"><span class="pre">read()</span></code> and <code class="docutils literal notranslate"><span class="pre">write()</span></code> functions to communicate.</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 – <sys/stat.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">int mkfifo (const char *pathname, mode_t mode);</span></code></dt>
|
||
<dd>Creates a new file identified by the pathname to use as a FIFO</dd>
|
||
</dl>
|
||
</div>
|
||
<p>A common use for FIFOs is to create client/server applications on the same machine. For example,
|
||
consider an anti-virus server that runs in the background, scanning for corrupted files. When the
|
||
system administrator wants to get a report on potentially bad files, they run a client application
|
||
that uses a FIFO to initiate contact with the server. Both the server and the client application are
|
||
distinct processes that are running separate programs. That is, neither process was created by
|
||
either of them calling <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. As such, an anonymous <code class="docutils literal notranslate"><span class="pre">pipe()</span></code> call would not work. Instead,
|
||
both processes use the name attached to the FIFO to set up the communication.</p>
|
||
<p>As a simple scenario, consider a server that prints hello whenever a client writes a non-zero value
|
||
to a file and shuts down when the client writes a zero. <a class="reference external" href="Pipes.html#cl3-4">Code Listing 3.4</a> shows the structure of the
|
||
server. The server starts by creating the FIFO with read and write permissions for the current user.
|
||
Then, the server opens the FIFO in read-only mode and enters the listening loop. Once the server
|
||
reads a value of 0 from the FIFO, it exits the loop, then closes and deletes the FIFO.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-4"><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
|
||
33
|
||
34</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.4:</span>
|
||
<span class="cm"> The basic structure of a server process using a FIFO</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="cm">/* Create the FIFO or die trying */</span>
|
||
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">FIFO</span> <span class="o">=</span> <span class="s">"/tmp/MY_FIFO"</span><span class="p">;</span>
|
||
<span class="n">assert</span> <span class="p">(</span><span class="n">mkfifo</span> <span class="p">(</span><span class="n">FIFO</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="o">==</span> <span class="mi">0</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Try to open the FIFO. Delete FIFO if open() fails */</span>
|
||
<span class="kt">int</span> <span class="n">fifo</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="n">FIFO</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">fifo</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">fprintf</span> <span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"Failed to open FIFO</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="n">unlink</span> <span class="p">(</span><span class="n">FIFO</span><span class="p">);</span>
|
||
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="cm">/* Main server loop */</span>
|
||
<span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="kt">int</span> <span class="n">req</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">read</span> <span class="p">(</span><span class="n">fifo</span><span class="p">,</span> <span class="o">&</span><span class="n">req</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">int</span><span class="p">))</span> <span class="o">!=</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">int</span><span class="p">))</span>
|
||
<span class="k">continue</span><span class="p">;</span>
|
||
|
||
<span class="cm">/* If we read a 0, quit; otherwise print hello */</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">req</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="k">break</span><span class="p">;</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"hello</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="cm">/* Read a 0 from the FIFO, so close and delete the FIFO */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">fifo</span><span class="p">);</span>
|
||
<span class="n">printf</span> <span class="p">(</span><span class="s">"Deleting FIFO</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
<span class="n">unlink</span> <span class="p">(</span><span class="n">FIFO</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p><a class="reference external" href="Pipes.html#cl3-5">Code Listing 3.5</a> shows a sample client. This client opens the FIFO, then writes a sequence of
|
||
integers (5 down to 0) into the FIFO. Note that anything the client writes after the 0 would be
|
||
thrown away, as the server would delete the FIFO at that point.</p>
|
||
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl3-5"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 3.5:</span>
|
||
<span class="cm"> A client process that sends six messages to the server in Code Listing 3.4</span>
|
||
<span class="cm"> */</span>
|
||
|
||
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">FIFO</span> <span class="o">=</span> <span class="s">"/tmp/MY_FIFO"</span><span class="p">;</span>
|
||
|
||
<span class="cm">/* Use the file name to open the FIFO for writing */</span>
|
||
<span class="kt">int</span> <span class="n">fifo</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="n">FIFO</span><span class="p">,</span> <span class="n">O_WRONLY</span><span class="p">);</span>
|
||
<span class="n">assert</span> <span class="p">(</span><span class="n">fifo</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
|
||
|
||
<span class="cm">/* Open the FIFO 6 times, writing an int each time */</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> <span class="n">index</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">index</span><span class="o">--</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="cm">/* Write 5, 4, 3, 2, 1, 0 into the FIFO */</span>
|
||
<span class="kt">int</span> <span class="n">msg</span> <span class="o">=</span> <span class="n">index</span><span class="p">;</span>
|
||
<span class="n">write</span> <span class="p">(</span><span class="n">fifo</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="kt">int</span><span class="p">));</span>
|
||
|
||
<span class="cm">/* Add a slight delay each time */</span>
|
||
<span class="n">sleep</span> <span class="p">(</span><span class="mi">1</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="cm">/* Close the FIFO */</span>
|
||
<span class="n">close</span> <span class="p">(</span><span class="n">fifo</span><span class="p">);</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>Although FIFOs use standard file I/O functions (e.g., <code class="docutils literal notranslate"><span class="pre">open()</span></code>, <code class="docutils literal notranslate"><span class="pre">read()</span></code>, and <code class="docutils literal notranslate"><span class="pre">write()</span></code>), it
|
||
is important to note that they are not regular files. Specifically, once data has been read from a
|
||
FIFO, the data is discarded and cannot be read again (just like an anonymous pipe). In contrast,
|
||
with a regular file, multiple processes can read the same data from the same file. That is, regular
|
||
files store data persistently, but FIFOs do not. Consequently, FIFOs cannot be used for broadcasting
|
||
a single message to multiple recipients; only one process can read the data. Similarly, FIFOs (like
|
||
pipes) are not suitable for bi-directional communication; if a process writes into the FIFO then
|
||
immediately tries to read a response, <strong>it may read its own message</strong>!</p>
|
||
<p>Also similar to anonymous pipes, FIFOs use <a class="reference internal" href="Glossary.html#term-blocking-i-o"><span class="xref std std-term">blocking I/O</span></a> until both ends are opened by at least
|
||
one process. As such, there is no concern about a process writing into the FIFO too soon; if no
|
||
process has opened the FIFO for reading, the writing process will block until a reader becomes
|
||
available. This behavior may be problematic if the writing process needs to perform some other task.
|
||
To resolve this problem, pass the <code class="docutils literal notranslate"><span class="pre">O_NONBLOCK</span></code> option during the call to <code class="docutils literal notranslate"><span class="pre">open()</span></code> to make the
|
||
FIFO access non-blocking.</p>
|
||
<div
|
||
id="IPCPipesSumm"
|
||
class="embedContainer"
|
||
data-exer-name="IPCPipesSumm"
|
||
data-long-name="Pipes and FIFOs questions"
|
||
data-short-name="IPCPipesSumm"
|
||
data-frame-src="../../../Exercises/IPC/IPCPipesSumm.html?selfLoggingEnabled=false&localMode=true&module=Pipes&JXOP-debug=true&JOP-lang=en&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="5"
|
||
data-type="ka"
|
||
data-exer-id="">
|
||
|
||
<div class="center">
|
||
<div id="IPCPipesSumm_iframe"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<div class="mt-4 container center">
|
||
«  <a id="prevmod1" href="IPCModels.html">3.2. IPC Models</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod1" href="MMap.html">3.4. Shared Memory With Memory-mapped Files</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> |