705 lines
59 KiB
HTML
705 lines
59 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|||
|
|
|||
|
<title>2.5. Process Life Cycle — 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="6. The UNIX File Abstraction" href="UnixFile.html" />
|
|||
|
<link rel="prev" title="4. System Call Interface" href="Syscall.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="ProcessCycle.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="ProcessCycle.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/ProcessCycle.rst"
|
|||
|
target="_blank" rel="nofollow">Show Source</a></li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
|
|||
|
<div class="container center">
|
|||
|
«  <a id="prevmod" href="Syscall.html">2.4. System Call Interface</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod" href="UnixFile.html">2.6. The UNIX File Abstraction</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 = "ProcessCycle";ODSA.SETTINGS.MODULE_LONG_NAME = "Process Life Cycle";ODSA.SETTINGS.MODULE_CHAPTER = "Processes and OS Basics"; ODSA.SETTINGS.BUILD_DATE = "2021-10-29 11:55:12"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="process-life-cycle">
|
|||
|
<h1>2.5. Process Life Cycle<a class="headerlink" href="ProcessCycle.html#process-life-cycle" title="Permalink to this headline">¶</a></h1>
|
|||
|
<p>From a very high-level perspective, we can describe the life cycle of a process as a sequence of
|
|||
|
<a class="reference internal" href="Glossary.html#term-event"><span class="xref std std-term">events</span></a>. The first event is the creation of the process as a new virtual memory
|
|||
|
instance. The CPU will then begin executing the program code according to the
|
|||
|
<em>von Neumann instruction cycle</em> until it reaches the <code class="docutils literal notranslate"><span class="pre">halt</span></code> instruction indicating the
|
|||
|
program is complete. At that point, the process is destroyed and any resources (such as physical
|
|||
|
memory) associated with it are reclaimed by the kernel.</p>
|
|||
|
<div class="section" id="process-creation">
|
|||
|
<h2>2.5.1. Process Creation<a class="headerlink" href="ProcessCycle.html#process-creation" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>There are generally two system calls that are associated with creating a new process: <code class="docutils literal notranslate"><span class="pre">fork()</span></code> and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">exec()</span></code>. When a program calls <code class="docutils literal notranslate"><span class="pre">fork()</span></code>, a system call is triggered that asks the kernel to
|
|||
|
create a new virtual memory instance. In the immediate moment when this occurs, the contents of the
|
|||
|
new virtual memory instance is an exact duplicate of the process that was running. We refer to the
|
|||
|
two processes as the <em>parent</em> and <em>child</em>. While
|
|||
|
handling the <code class="docutils literal notranslate"><span class="pre">fork()</span></code>, the kernel will allocate new internal data structures for the child, assign
|
|||
|
it a <a class="reference internal" href="Glossary.html#term-process-identifier"><span class="xref std std-term">process identifier</span></a> (PID), and assign a small set of initial resources to it. A PID is
|
|||
|
an integer value that acts like a name that can be used to uniquely refer to a process.</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">pid_t fork(void);</span></code></dt>
|
|||
|
<dd>Creates a new process. Returns the child’s PID if successful.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">pid_t getpid(void);</span></code></dt>
|
|||
|
<dd>Gets the current process’s PID.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">pid_t getppid(void);</span></code></dt>
|
|||
|
<dd>Gets the PID of the current process’s parent.</dd>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
<p><a class="reference external" href="ProcessCycle.html#cl2-6">Code Listing 2.6</a> demonstrates how to use <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. Once both processes are running, the code can
|
|||
|
distinguish between the parent and child by looking at the value returned from <code class="docutils literal notranslate"><span class="pre">fork()</span></code>.The kernel
|
|||
|
returns 0 to the child, and it returns the child’s PID to the parent. If the kernel failed or
|
|||
|
refused to create a new process for some reason, it would return a negative value to the parent; the
|
|||
|
global variable <code class="docutils literal notranslate"><span class="pre">errno</span></code> (declared in the standard library file <code class="docutils literal notranslate"><span class="pre">errno.h</span></code>) would be set to an
|
|||
|
integer value indicating the error that occurred.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-6"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.6:</span>
|
|||
|
<span class="cm"> Using fork() to create a child process and access its PID</span>
|
|||
|
<span class="cm"> */</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="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="n">printf</span> <span class="p">(</span><span class="s">"ERROR: No child process created</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
|||
|
<span class="k">else</span> <span class="nf">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="n">printf</span> <span class="p">(</span><span class="s">"Hi, I am the child!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
|||
|
<span class="k">else</span>
|
|||
|
<span class="nf">printf</span> <span class="p">(</span><span class="s">"Parent just learned about child %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">child_pid</span><span class="p">);</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<p>The return values from <code class="docutils literal notranslate"><span class="pre">fork()</span></code> make sense when you consider that the C library defines two
|
|||
|
functions that allow the process to determine its own PID (<code class="docutils literal notranslate"><span class="pre">getpid()</span></code>) and to find out its
|
|||
|
parent’s PID (<code class="docutils literal notranslate"><span class="pre">getppid()</span></code>). The child can use these two functions to identify itself and its
|
|||
|
parent. However, the parent process may have already created dozens of child processes. The return
|
|||
|
value from <code class="docutils literal notranslate"><span class="pre">fork()</span></code> informs the parent of the PID for this new child process that was just created.</p>
|
|||
|
<p><a class="reference external" href="ProcessCycle.html#cl2-7">Code Listing 2.7</a> shows an example of what happens when the return code from <code class="docutils literal notranslate"><span class="pre">fork()</span></code> is not
|
|||
|
checked. On line 6, the original process creates a child. For clarity, let the original process of
|
|||
|
PID 1000 and this child has PID 1001. Since both processes continue to execute with the same code,
|
|||
|
both reach line 9 and create two additional processes (PIDs 1002 and 1003). As a result, there would
|
|||
|
be four processes that execute line 12, printing the message four times (with different PIDs each time).</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-7"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
|||
|
2
|
|||
|
3
|
|||
|
4
|
|||
|
5
|
|||
|
6
|
|||
|
7
|
|||
|
8
|
|||
|
9
|
|||
|
10
|
|||
|
11
|
|||
|
12
|
|||
|
13</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.7:</span>
|
|||
|
<span class="cm"> Running the same code in multiple processes</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="cm">/* Start by creating a second process */</span>
|
|||
|
<span class="kt">pid_t</span> <span class="n">first_fork</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">();</span>
|
|||
|
|
|||
|
<span class="cm">/* BOTH the original parent and child create new processes */</span>
|
|||
|
<span class="kt">pid_t</span> <span class="n">second_fork</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">();</span>
|
|||
|
|
|||
|
<span class="cm">/* This line will print four times */</span>
|
|||
|
<span class="n">printf</span> <span class="p">(</span><span class="s">"Hello world from %d!</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">getpid</span> <span class="p">());</span>
|
|||
|
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<p>It may seem odd that <code class="docutils literal notranslate"><span class="pre">fork()</span></code> would create a new process running the exact same code as the
|
|||
|
parent. However, there are several times where this makes sense. Consider a web browser, such as
|
|||
|
Google Chrome. Whenever you open a new tab, Chrome will make a call to <code class="docutils literal notranslate"><span class="pre">fork()</span></code> to create a new
|
|||
|
process for that tab. Intuitively, all tabs in a web browser work the same way: they get a URL
|
|||
|
request from the user and retrieve the corresponding web page or file from a server somewhere.
|
|||
|
Consequently, it makes sense that all of the processes for Chrome would start with the same code
|
|||
|
segment. Making the tabs run in separate processes provides some security and reliability: If a
|
|||
|
plug-in crashes in one tab, only that tab is affected; the other tabs exist in other processes, so
|
|||
|
they are isolated from the crash.</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>Once a process uses <code class="docutils literal notranslate"><span class="pre">fork()</span></code> to create a child process, the timing of the execution becomes
|
|||
|
nondeterministic from the programmer’s point of view. The programmer cannot predict or control when
|
|||
|
the child begins executing relative to the parent. In some systems, the child process may begin
|
|||
|
executing immediately before the parent process returns from the call to <code class="docutils literal notranslate"><span class="pre">fork()</span></code>. In others, the
|
|||
|
child may simply be created and start running at some later time. Consequently, if the order of the
|
|||
|
execution matters, the programmer must take extra steps to ensure correct behavior; one example of
|
|||
|
this is to use <code class="docutils literal notranslate"><span class="pre">wait()</span></code> as described below. We will examine more advanced techniques in later chapters.</p>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="switching-program-code">
|
|||
|
<h2>2.5.2. Switching Program Code<a class="headerlink" href="ProcessCycle.html#switching-program-code" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>In many cases, after making a call to <code class="docutils literal notranslate"><span class="pre">fork()</span></code>, you want to switch to a different program. For
|
|||
|
instance, consider the <code class="docutils literal notranslate"><span class="pre">bash</span></code> terminal program. Within <code class="docutils literal notranslate"><span class="pre">bash</span></code>, some commands are considered
|
|||
|
<em>built-in</em> and are executed by <code class="docutils literal notranslate"><span class="pre">bash</span></code> itself. One example of a built-in is the export command,
|
|||
|
which can be used to define or change an <a class="reference internal" href="Glossary.html#term-environment-variable"><span class="xref std std-term">environment variable</span></a>, such as <code class="docutils literal notranslate"><span class="pre">PATH</span></code> or
|
|||
|
<code class="docutils literal notranslate"><span class="pre">CLASSPATH</span></code>. Other commands are used to call a separate compiled program, such as <code class="docutils literal notranslate"><span class="pre">ls</span></code>, <code class="docutils literal notranslate"><span class="pre">gcc</span></code>,
|
|||
|
or <code class="docutils literal notranslate"><span class="pre">vim</span></code>. The code to execute these commands does not exist as a part of <code class="docutils literal notranslate"><span class="pre">bash</span></code>. Rather, these
|
|||
|
are distinct programs and the code needs to be loaded into the new process.</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 execl(const char *path, const char *arg0, ...</span>  <span class="pre">/*,</span> <span class="pre">(char *)0 */);</span></code></dt>
|
|||
|
<dd>Executes the program identified by the exact path.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int execle(const char *path, const char *arg0, ...</span>  <span class="pre">/*, (char *)0, char*</span> <span class="pre">const envp[]*/);</span></code></dt>
|
|||
|
<dd>Executes the program at path and set environment variables.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int execlp(const char *file, const char *arg0, ...</span>  <span class="pre">/*, (char *)0 */);</span></code></dt>
|
|||
|
<dd>Looks up the program file in the current <code class="docutils literal notranslate"><span class="pre">PATH</span></code>.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int execv(const char *path, char *const argv[]);</span></code></dt>
|
|||
|
<dd>Like execl, but command-line arguments are in an array.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int execve(const char *path, char *const argv[], char *const envp[]);</span></code></dt>
|
|||
|
<dd>Like execle, but command-line arguments are in an array.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int execvp(const char *file, char *const argv[]);</span></code></dt>
|
|||
|
<dd>Like execlp, but command-line arguments are in an array.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int fexecve(int fd, char *const argv[], char *const envp[]);</span></code></dt>
|
|||
|
<dd>Executes the program stored in an open file handle fd.</dd>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
<p>Loading a new program is handled by the <code class="docutils literal notranslate"><span class="pre">exec()</span></code> system call, which can be invoked by a family of
|
|||
|
C functions. The functions differ by how you pass the parameters. The <code class="docutils literal notranslate"><span class="pre">execl()</span></code>, <code class="docutils literal notranslate"><span class="pre">execle()</span></code>, and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">execlp()</span></code> functions take the command line arguments as additional function parameters, whereas
|
|||
|
execv(), execve(), and execvp() require you to create a single array that contains all of the
|
|||
|
arguments. The <code class="docutils literal notranslate"><span class="pre">execl()</span></code> and <code class="docutils literal notranslate"><span class="pre">execv()</span></code> functions expect that you provide the exact path to the
|
|||
|
executable file, while <code class="docutils literal notranslate"><span class="pre">execlp()</span></code> and <code class="docutils literal notranslate"><span class="pre">execvp()</span></code> will look up the path for you. The <code class="docutils literal notranslate"><span class="pre">execle()</span></code>
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">execve()</span></code> functions allow you to specify a custom set of environment variables for the new
|
|||
|
program. Finally, <code class="docutils literal notranslate"><span class="pre">fexecve()</span></code> allows you to pass an open file descriptor for the program instead
|
|||
|
of the program’s name or path. <a class="reference external" href="ProcessCycle.html#cl2-8">Code Listings 2.8</a> and <a class="reference external" href="ProcessCycle.html#cl2-9">2.9</a> show two different ways to
|
|||
|
call the <code class="docutils literal notranslate"><span class="pre">ls</span></code> program to list files, one using <code class="docutils literal notranslate"><span class="pre">execl()</span></code> and the other using <code class="docutils literal notranslate"><span class="pre">execvp()</span></code>.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-8"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
|||
|
2
|
|||
|
3
|
|||
|
4
|
|||
|
5
|
|||
|
6
|
|||
|
7
|
|||
|
8
|
|||
|
9
|
|||
|
10
|
|||
|
11
|
|||
|
12
|
|||
|
13
|
|||
|
14
|
|||
|
15
|
|||
|
16
|
|||
|
17
|
|||
|
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.8:</span>
|
|||
|
<span class="cm"> Using execl() lists all parameters in one list and requires an exact path</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="cm">/* Create the child and run 'ls -l' */</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="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="n">exit</span> <span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="cm">/* exit if fork() failed */</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="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">execl</span> <span class="p">(</span><span class="s">"/bin/ls"</span><span class="p">,</span> <span class="s">"ls"</span><span class="p">,</span> <span class="s">"-l"</span><span class="p">,</span> <span class="nb">NULL</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">/* exit if exec fails */</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="cm">/* Make the parent wait for the first child */</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>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-9"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
|||
|
2
|
|||
|
3
|
|||
|
4
|
|||
|
5
|
|||
|
6
|
|||
|
7
|
|||
|
8
|
|||
|
9
|
|||
|
10
|
|||
|
11
|
|||
|
12
|
|||
|
13
|
|||
|
14
|
|||
|
15
|
|||
|
16
|
|||
|
17
|
|||
|
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.9:</span>
|
|||
|
<span class="cm"> Using execvp() puts command-line arguments in a vector and does a path lookup</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="cm">/* Set up all parameters for 'ls -l' in a single vector */</span>
|
|||
|
<span class="kt">char</span> <span class="o">*</span><span class="k">const</span> <span class="n">parameters</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="s">"ls"</span><span class="p">,</span> <span class="s">"-l"</span><span class="p">,</span> <span class="nb">NULL</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="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="n">exit</span> <span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="cm">/* exit if fork() failed */</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="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">execvp</span> <span class="p">(</span><span class="s">"ls"</span><span class="p">,</span> <span class="n">parameters</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">/* exit if exec fails */</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="cm">/* Make the parent wait for the second child */</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>There are a couple of important points to note in this code. First, note that both calls to <code class="docutils literal notranslate"><span class="pre">ls</span></code>
|
|||
|
will have the same three arguments (<code class="docutils literal notranslate"><span class="pre">argv[0]</span> <span class="pre">=</span> <span class="pre">"ls"</span></code>, <code class="docutils literal notranslate"><span class="pre">argv[1]</span> <span class="pre">=</span> <span class="pre">"-l"</span></code>, and <code class="docutils literal notranslate"><span class="pre">argv[2]</span> <span class="pre">=</span> <span class="pre">NULL</span></code>).
|
|||
|
That is, the first parameter passed to <code class="docutils literal notranslate"><span class="pre">execl()</span></code> on line 12 of <a class="reference external" href="ProcessCycle.html#cl2-8">Code Listing 2.8</a> is not included in
|
|||
|
the argument list as the child process receives it. The convention that <code class="docutils literal notranslate"><span class="pre">argv[0]</span></code> is the name of
|
|||
|
the program arises from how programs like bash specify the remaining parameters to the <code class="docutils literal notranslate"><span class="pre">exec()</span></code> functions.</p>
|
|||
|
<p>Second, observe that both versions use <code class="docutils literal notranslate"><span class="pre">NULL</span></code> to indicate the end of the arguments. In the case of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">execl()</span></code>, function takes a variable-length parameter list, so it relies on <code class="docutils literal notranslate"><span class="pre">NULL</span></code> to know when
|
|||
|
it should stop looking for arguments. In the case of <code class="docutils literal notranslate"><span class="pre">execvp()</span></code>, the function expects exactly two
|
|||
|
arguments, with the second being an array of unknown length.</p>
|
|||
|
<p>Third, note that the first parameter of <code class="docutils literal notranslate"><span class="pre">execl()</span></code> must be an exact path to the location of the
|
|||
|
executable file. If you call <code class="docutils literal notranslate"><span class="pre">execl()</span></code> with just <code class="docutils literal notranslate"><span class="pre">"ls"</span></code> instead of <code class="docutils literal notranslate"><span class="pre">"/bin/ls"</span></code>, then it will
|
|||
|
look for an executable file in the current directory that is named <code class="docutils literal notranslate"><span class="pre">ls</span></code>. If the file does not
|
|||
|
exist, the call to <code class="docutils literal notranslate"><span class="pre">execl()</span></code> will return a negative value to indicate an error. For the call to
|
|||
|
<code class="docutils literal notranslate"><span class="pre">execvp()</span></code>, bash will look through the directories specified by the <code class="docutils literal notranslate"><span class="pre">PATH</span></code> environment variable
|
|||
|
to try to find the executable file for you. If line 12 of <a class="reference external" href="ProcessCycle.html#cl2-8">Code Listing 2.8</a> used <code class="docutils literal notranslate"><span class="pre">execlp()</span></code> instead
|
|||
|
of <code class="docutils literal notranslate"><span class="pre">execl()</span></code>, <code class="docutils literal notranslate"><span class="pre">bash</span></code> would perform a <code class="docutils literal notranslate"><span class="pre">PATH</span></code> lookup there, as well.</p>
|
|||
|
<p>Finally, note that no code after a successful call to any of the <code class="docutils literal notranslate"><span class="pre">exec()</span></code> functions will execute
|
|||
|
in the current process. In this case, <a class="reference external" href="ProcessCycle.html#cl2-8">Code Listing 2.8</a> line 13 and <a class="reference external" href="ProcessCycle.html#cl2-9">Code Listing 2.9</a> line 14 should
|
|||
|
never be reached, so neither of the calls to <code class="docutils literal notranslate"><span class="pre">exit()</span></code> should happen. The reason is that <code class="docutils literal notranslate"><span class="pre">exec()</span></code>
|
|||
|
<strong>replaces the current process’s code, data, stack, and heap segments</strong>. Assuming the call to
|
|||
|
<code class="docutils literal notranslate"><span class="pre">exec()</span></code> is successful, the child process will start over with a clean virtual memory instance;
|
|||
|
none of the parent process’s information is retained within the child process.</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>Always make sure to check the return values for both <code class="docutils literal notranslate"><span class="pre">fork()</span></code> and <code class="docutils literal notranslate"><span class="pre">exec()</span></code>. Most OS enforce a
|
|||
|
limit on the number of processes that a single user can create; once you reach this limit,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">fork()</span></code> will fail. Similarly, if you make a mistake in the name of the file that you want to run
|
|||
|
or you do not have permissions, <code class="docutils literal notranslate"><span class="pre">exec()</span></code> will fail and the child process will continue to execute
|
|||
|
the current program’s code. Failing to check these return values can lead to unexpected behavior.</p>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="posix-spawn-interface">
|
|||
|
<h2>2.5.3. POSIX Spawn Interface<a class="headerlink" href="ProcessCycle.html#posix-spawn-interface" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>In recent years, the use of <code class="docutils literal notranslate"><span class="pre">fork()</span></code> has been criticized for a variety of reasons. For instance,
|
|||
|
the implementation requirements of it are considered too slow and require too much power for very
|
|||
|
small embedded computing systems (e.g., think of the “computers” in a car that operate the cruise
|
|||
|
control or anti-lock breaking). Another problem is that calling <code class="docutils literal notranslate"><span class="pre">fork()</span></code> on a process with
|
|||
|
multiple threads (see Chapter 7) can lead to inconsistent copies of the parent process; that is, the
|
|||
|
thread that calls <code class="docutils literal notranslate"><span class="pre">fork()</span></code> might not have a completely accurate memory image, particularly in
|
|||
|
<a class="reference internal" href="Glossary.html#term-multicore"><span class="xref std std-term">multicore</span></a> architectures. Lastly, the semantics of <code class="docutils literal notranslate"><span class="pre">fork()</span></code> have
|
|||
|
become very complicated, as there are many special cases that must be handled, such as how to deal
|
|||
|
with open files, timers, asynchronous I/O buffers, etc. <a class="footnote-reference" href="ProcessCycle.html#f14" id="id4">[1]</a></p>
|
|||
|
<p>To address some of these criticisms, POSIX includes a new function interface, <code class="docutils literal notranslate"><span class="pre">posix_spawn()</span></code>.
|
|||
|
This function takes multiple parameters, including the path to the executable and the <code class="docutils literal notranslate"><span class="pre">argv</span></code> and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">envp</span></code> arrays that would be passed into <code class="docutils literal notranslate"><span class="pre">execv()</span></code> or <code class="docutils literal notranslate"><span class="pre">execve()</span></code> functions. In addition,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">posix_spawn()</span></code> takes other parameters that can specify additional operations. These operations
|
|||
|
give the programmer explicit control over the special cases mentioned above.</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 – <spawn.h></p><hr class="mt-1" />
|
|||
|
<dl class="docutils">
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">posix_spawn(pid_t</span> <span class="pre">*pid,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*path,</span> <span class="pre">const</span> <span class="pre">posix_spawn_file_actions_t</span> <span class="pre">*file_actions,</span> <span class="pre">const</span> <span class="pre">posix_spawnattr_t</span> <span class="pre">*attrp,</span> <span class="pre">char</span> <span class="pre">*const</span> <span class="pre">argv[],</span> <span class="pre">char</span> <span class="pre">*const</span> <span class="pre">envp[]);</span></code></dt>
|
|||
|
<dd>Create a new process and load the code identified by the path in a single call.</dd>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
<p><a class="reference external" href="ProcessCycle.html#cl2-10">Code Listing 2.10</a> shows how to use <code class="docutils literal notranslate"><span class="pre">posix_spawn()</span></code> to run an external program. In this case, the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">cksum</span></code> program is run on a CSV file, as specified in the <code class="docutils literal notranslate"><span class="pre">path</span></code> and <code class="docutils literal notranslate"><span class="pre">argv</span></code> arguments. The
|
|||
|
child’s process ID is returned through the call-by-reference parameter <code class="docutils literal notranslate"><span class="pre">&child</span></code>. The <code class="docutils literal notranslate"><span class="pre">assert()</span></code>
|
|||
|
is used here to confirm that the process was successfully spawned; <code class="docutils literal notranslate"><span class="pre">posix_spawn()</span></code> returns a
|
|||
|
non-zero value if an error occurs at any point and the process was not successfully spawned.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-10"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.10:</span>
|
|||
|
<span class="cm"> Using posix_spawn() to run a helper program instead of fork() and execv()</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="kt">pid_t</span> <span class="n">child</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
|
|||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">path</span> <span class="o">=</span> <span class="s">"/usr/bin/cksum"</span><span class="p">;</span>
|
|||
|
<span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="s">"cksum"</span><span class="p">,</span> <span class="s">"movies.csv"</span><span class="p">,</span> <span class="nb">NULL</span> <span class="p">};</span>
|
|||
|
|
|||
|
<span class="cm">/* Spawn and run an external program in one step */</span>
|
|||
|
<span class="n">assert</span> <span class="p">(</span><span class="n">posix_spawn</span> <span class="p">(</span><span class="o">&</span><span class="n">child</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">argv</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="cm">/* Make the parent wait for the child */</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>
|
|||
|
</div>
|
|||
|
<div class="section" id="process-destruction">
|
|||
|
<h2>2.5.4. Process Destruction<a class="headerlink" href="ProcessCycle.html#process-destruction" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>A process can be terminated in a number of ways. Some methods of process termination are voluntary
|
|||
|
in nature, such as when the code makes a call to <code class="docutils literal notranslate"><span class="pre">exit()</span></code>, <code class="docutils literal notranslate"><span class="pre">abort()</span></code>, or returns from
|
|||
|
<code class="docutils literal notranslate"><span class="pre">main()</span></code>. Other methods are involuntary, such as when a process is killed after a segmentation
|
|||
|
fault or similar exception. Regardless of what causes the process termination, the same set of
|
|||
|
procedures are typically performed: open file handles are closed, the virtual memory space is
|
|||
|
destroyed, the associated physical memory is reclaimed by the system, and any relevant data
|
|||
|
structures in the kernel are cleaned up.</p>
|
|||
|
<p>The preceding example also illustrates a key element about the timing of the destruction of
|
|||
|
processes. Once a process calls <code class="docutils literal notranslate"><span class="pre">fork()</span></code> and creates a child process, the relative scheduling
|
|||
|
between the parent and child is nondeterministic from the programmer’s perspective. The two
|
|||
|
processes are scheduled independently by the OS running on that particular machine, and the
|
|||
|
scheduling will be influenced by other processes running, as well. However, the parent can
|
|||
|
temporarily pause its own execution by making a call to <code class="docutils literal notranslate"><span class="pre">wait()</span></code> or <code class="docutils literal notranslate"><span class="pre">waitpid()</span></code>.</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/wait.h></p><hr class="mt-1" />
|
|||
|
<dl class="docutils">
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">pid_t wait(int *stat_loc);</span></code></dt>
|
|||
|
<dd>Waits on all children, gets status information in stat_loc.</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">pid_t waitpid(pid_t pid, int *stat_loc, int options);</span></code></dt>
|
|||
|
<dd>Waits on a particular child process identified by pid.</dd>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">wait()</span></code> system call will block the current process until all of its children have been
|
|||
|
terminated. A call to <code class="docutils literal notranslate"><span class="pre">waitpid()</span></code> is similar, but it only waits for a single, identified child to
|
|||
|
terminate. In the preceding example, the first child makes a call to <code class="docutils literal notranslate"><span class="pre">execl()</span></code> to run the <code class="docutils literal notranslate"><span class="pre">ls</span></code>
|
|||
|
program. At approximately the same time, the parent process calls <code class="docutils literal notranslate"><span class="pre">wait(NULL)</span></code>. The
|
|||
|
nondeterministic nature of scheduling means it is impossible to determine which happens first, but
|
|||
|
the result is the same: the parent process will not proceed to the second call to <code class="docutils literal notranslate"><span class="pre">fork()</span></code> until
|
|||
|
the first child process runs the <code class="docutils literal notranslate"><span class="pre">ls</span></code> program and terminates.</p>
|
|||
|
<p>Note that there is no problem even if the child process terminates before the parent gets scheduled
|
|||
|
to run. If all children have been terminated by the time a process calls <code class="docutils literal notranslate"><span class="pre">wait()</span></code>, then the parent
|
|||
|
process will simply continue on without pausing. The only requirement for <code class="docutils literal notranslate"><span class="pre">wait()</span></code> is that the
|
|||
|
parent cannot continue if there is at least one child process still trying to run.</p>
|
|||
|
<p>The convention with C programs is to return an integer value from <code class="docutils literal notranslate"><span class="pre">main()</span></code> to indicate whether the
|
|||
|
program completed successfully. The standard practice is to return 0 to indicate that no error
|
|||
|
occurred, whereas a non-zero value typically indicates an error occurred in some way. When working
|
|||
|
on the command-line, this value can be retrieved by printing the <code class="docutils literal notranslate"><span class="pre">bash</span></code> variable <code class="docutils literal notranslate"><span class="pre">$?</span></code>. In C
|
|||
|
programs, this value can be retrieved through the <code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">*</span></code> parameter passed to <code class="docutils literal notranslate"><span class="pre">wait()</span></code> as shown
|
|||
|
in <a class="reference external" href="ProcessCycle.html#cl2-11">Code Listing 2.11</a>.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl2-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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 2.11:</span>
|
|||
|
<span class="cm"> Using wait() and WEXITSTATUS() to retrieve a process's return code</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="cm">/* Create the first child and run 'ls -l' */</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="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="n">exit</span> <span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="cm">/* exit if fork() failed */</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="n">exit</span> <span class="p">(</span><span class="mi">23</span><span class="p">);</span> <span class="cm">/* child process exits */</span>
|
|||
|
|
|||
|
<span class="cm">/* Make the parent wait to retrieve the return code*/</span>
|
|||
|
<span class="kt">int</span> <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|||
|
<span class="kt">pid_t</span> <span class="n">exited</span> <span class="o">=</span> <span class="n">wait</span> <span class="p">(</span><span class="o">&</span><span class="n">status</span><span class="p">);</span>
|
|||
|
|
|||
|
<span class="cm">/* Make the parent print the child's exit code of 23 */</span>
|
|||
|
<span class="n">printf</span> <span class="p">(</span><span class="s">"PID %d exited with code %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">exited</span><span class="p">,</span> <span class="n">WEXITSTATUS</span><span class="p">(</span><span class="n">status</span><span class="p">));</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
|
|||
|
<div class="figure align-left">
|
|||
|
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
|
|||
|
</div>
|
|||
|
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
|
|||
|
<p>The return value of the child process is shifted to the left when it is retrieved using <code class="docutils literal notranslate"><span class="pre">wait()</span></code>,
|
|||
|
as the lower eight bits are used for other purposes. The <code class="docutils literal notranslate"><span class="pre">WEXITSTATUS()</span></code> macro corrects this bit
|
|||
|
shifting to receive the actual return code from the child process.</p>
|
|||
|
</div>
|
|||
|
<table class="docutils footnote" frame="void" id="f14" rules="none">
|
|||
|
<colgroup><col class="label" /><col /></colgroup>
|
|||
|
<tbody valign="top">
|
|||
|
<tr><td class="label"><a class="fn-backref" href="ProcessCycle.html#id4">[1]</a></td><td>For a full description of the problems with <code class="docutils literal notranslate"><span class="pre">fork()</span></code>, see the paper: A. Baumann, J.
|
|||
|
Appavoo, O. Krieger, and T. Roscoe, “A <code class="docutils literal notranslate"><span class="pre">fork()</span></code> in the road.” In Workshop on Hot Topics in Operating
|
|||
|
Systems (HotOS ‘19). New York, NY: ACM, 2019.</td></tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
<div
|
|||
|
id="ProcessLifeSumm"
|
|||
|
class="embedContainer"
|
|||
|
data-exer-name="ProcessLifeSumm"
|
|||
|
data-long-name="Process life cycle questions"
|
|||
|
data-short-name="ProcessLifeSumm"
|
|||
|
data-frame-src="../../../Exercises/Processes/ProcessLifeSumm.html?selfLoggingEnabled=false&localMode=true&module=ProcessCycle&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="7"
|
|||
|
data-type="ka"
|
|||
|
data-exer-id="">
|
|||
|
|
|||
|
<div class="center">
|
|||
|
<div id="ProcessLifeSumm_iframe"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="container">
|
|||
|
|
|||
|
<div class="mt-4 container center">
|
|||
|
«  <a id="prevmod1" href="Syscall.html">2.4. System Call Interface</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod1" href="UnixFile.html">2.6. The UNIX File Abstraction</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>
|