Files
rust-based-os-comp2022/chapter5/1process.html
2022-06-30 04:46:48 +00:00

619 lines
59 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html class="no-js" lang="zh_CN">
<head><meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="color-scheme" content="light dark"><link rel="index" title="索引" href="../genindex.html" /><link rel="search" title="搜索" href="../search.html" /><link rel="next" title="进程管理的核心数据结构" href="2core-data-structures.html" /><link rel="prev" title="引言" href="0intro.html" />
<meta name="generator" content="sphinx-4.1.2, furo 2021.08.31"/>
<title>与进程有关的重要系统调用 - Open-Source-OS-Training-Camp-2022 文档</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=c7c65a82b42f6b978e58466c1e9ef2509836d916" />
<link rel="stylesheet" type="text/css" href="../_static/tabs.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo-extensions.css?digest=16fb25fabf47304eee183a5e9af80b1ba98259b1" />
<link rel="stylesheet" type="text/css" href="../_static/my_style.css" />
<style>
body {
--color-code-background: #f8f8f8;
--color-code-foreground: black;
}
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
}
</style></head>
<body>
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-toc" viewBox="0 0 24 24">
<title>Contents</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" />
<line x1="4" y1="6" x2="20" y2="6" />
<line x1="10" y1="12" x2="20" y2="12" />
<line x1="6" y1="18" x2="20" y2="18" />
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24">
<title>Light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24">
<title>Dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
</symbol>
<symbol id="svg-sun-half" viewBox="0 0 24 24">
<title>Auto light/dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="9" />
<path d="M13 12h5" />
<path d="M13 15h4" />
<path d="M13 18h1" />
<path d="M13 9h4" />
<path d="M13 6h1" />
</svg>
</symbol>
</svg>
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
<label class="overlay sidebar-overlay" for="__navigation">
<div class="visually-hidden">Hide navigation sidebar</div>
</label>
<label class="overlay toc-overlay" for="__toc">
<div class="visually-hidden">Hide table of contents sidebar</div>
</label>
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<div class="visually-hidden">Toggle site navigation sidebar</div>
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
</label>
</div>
<div class="header-center">
<a href="../index.html"><div class="brand">Open-Source-OS-Training-Camp-2022 文档</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
<span class="sidebar-brand-text">Open-Source-OS-Training-Camp-2022 文档</span>
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
<input class="sidebar-search" placeholder=搜索 name="q" aria-label="搜索">
<input type="hidden" name="check_keywords" value="yes">
<input type="hidden" name="area" value="default">
</form>
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
<p class="caption" role="heading"><span class="caption-text">正文</span></p>
<ul class="current">
<li class="toctree-l1 has-children"><a class="reference internal" href="../0setup-devel-env.html">第零章:实验环境配置</a><input class="toctree-checkbox" id="toctree-checkbox-1" name="toctree-checkbox-1" role="switch" type="checkbox"/><label for="toctree-checkbox-1"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter1/index.html">第一章:应用程序与基本执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-2" name="toctree-checkbox-2" role="switch" type="checkbox"/><label for="toctree-checkbox-2"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter1/0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/1app-ee-platform.html">应用程序执行环境与平台支持</a><input class="toctree-checkbox" id="toctree-checkbox-3" name="toctree-checkbox-3" role="switch" type="checkbox"/><label for="toctree-checkbox-3"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/2remove-std.html">移除标准库依赖</a><input class="toctree-checkbox" id="toctree-checkbox-4" name="toctree-checkbox-4" role="switch" type="checkbox"/><label for="toctree-checkbox-4"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/3mini-rt-usrland.html">构建用户态执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-5" name="toctree-checkbox-5" role="switch" type="checkbox"/><label for="toctree-checkbox-5"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/4mini-rt-baremetal.html">构建裸机执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter2/index.html">第二章:批处理系统</a><input class="toctree-checkbox" id="toctree-checkbox-7" name="toctree-checkbox-7" role="switch" type="checkbox"/><label for="toctree-checkbox-7"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter2/0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/2application.html">实现应用程序</a><input class="toctree-checkbox" id="toctree-checkbox-8" name="toctree-checkbox-8" role="switch" type="checkbox"/><label for="toctree-checkbox-8"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/3batch-system.html">实现批处理操作系统</a><input class="toctree-checkbox" id="toctree-checkbox-9" name="toctree-checkbox-9" role="switch" type="checkbox"/><label for="toctree-checkbox-9"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/4trap-handling.html">实现特权级的切换</a><input class="toctree-checkbox" id="toctree-checkbox-10" name="toctree-checkbox-10" role="switch" type="checkbox"/><label for="toctree-checkbox-10"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter3/index.html">第三章:多道程序与分时多任务</a><input class="toctree-checkbox" id="toctree-checkbox-11" name="toctree-checkbox-11" role="switch" type="checkbox"/><label for="toctree-checkbox-11"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/1multi-loader.html">多道程序放置与加载</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/2task-switching.html">任务切换</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/3multiprogramming.html">管理多道程序</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/4time-sharing-system.html">分时多任务系统</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/5exercise.html">chapter3练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter4/index.html">第四章:地址空间</a><input class="toctree-checkbox" id="toctree-checkbox-12" name="toctree-checkbox-12" role="switch" type="checkbox"/><label for="toctree-checkbox-12"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/3sv39-implementation-1.html">实现 SV39 多级页表机制(上)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/4sv39-implementation-2.html">实现 SV39 多级页表机制(下)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/5kernel-app-spaces.html">内核与应用的地址空间</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/6multitasking-based-on-as.html">基于地址空间的分时多任务</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/7exercise.html">chapter4练习</a></li>
</ul>
</li>
<li class="toctree-l1 current has-children"><a class="reference internal" href="index.html">第五章:进程及进程管理</a><input checked="" class="toctree-checkbox" id="toctree-checkbox-13" name="toctree-checkbox-13" role="switch" type="checkbox"/><label for="toctree-checkbox-13"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="0intro.html">引言</a></li>
<li class="toctree-l2 current current-page"><a class="current reference internal" href="#">与进程有关的重要系统调用</a></li>
<li class="toctree-l2"><a class="reference internal" href="2core-data-structures.html">进程管理的核心数据结构</a></li>
<li class="toctree-l2"><a class="reference internal" href="3implement-process-mechanism.html">进程管理机制的设计实现</a></li>
<li class="toctree-l2"><a class="reference internal" href="4exercise.html">chapter5练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter6/index.html">第六章文件系统与I/O重定向</a><input class="toctree-checkbox" id="toctree-checkbox-14" name="toctree-checkbox-14" role="switch" type="checkbox"/><label for="toctree-checkbox-14"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/1file-descriptor.html">文件与文件描述符</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/1fs-interface.html">文件系统接口</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/2fs-implementation-1.html">简易文件系统 easy-fs (上)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/2fs-implementation-2.html">简易文件系统 easy-fs (下)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/3using-easy-fs-in-kernel.html">在内核中使用 easy-fs</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter6/4exercise.html">chapter6练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter7/index.html">第七章:进程间通信</a><input class="toctree-checkbox" id="toctree-checkbox-15" name="toctree-checkbox-15" role="switch" type="checkbox"/><label for="toctree-checkbox-15"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/1pipe.html">管道</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/2cmdargs-and-redirection.html">命令行参数与标准 I/O 重定向</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter7/3exercise.html">chapter7练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter8/index.html">第八章:并发</a><input class="toctree-checkbox" id="toctree-checkbox-16" name="toctree-checkbox-16" role="switch" type="checkbox"/><label for="toctree-checkbox-16"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/1thread-kernel.html">内核态的线程管理</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/2lock.html">锁机制</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/3semaphore.html">信号量机制</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/4condition-variable.html">条件变量机制</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter8/5exercise.html">chapter8 练习</a></li>
</ul>
</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">附录</span></p>
<ul>
<li class="toctree-l1 has-children"><a class="reference internal" href="../appendix-a/index.html">附录 ARust 系统编程资料</a><input class="toctree-checkbox" id="toctree-checkbox-17" name="toctree-checkbox-17" role="switch" type="checkbox"/><label for="toctree-checkbox-17"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../appendix-b/index.html">附录 B常见工具的使用方法</a><input class="toctree-checkbox" id="toctree-checkbox-18" name="toctree-checkbox-18" role="switch" type="checkbox"/><label for="toctree-checkbox-18"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../appendix-c/index.html">附录 C深入机器模式RustSBI</a><input class="toctree-checkbox" id="toctree-checkbox-19" name="toctree-checkbox-19" role="switch" type="checkbox"/><label for="toctree-checkbox-19"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../appendix-d/index.html">附录 DRISC-V相关信息</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">开发注记</span></p>
<ul>
<li class="toctree-l1 has-children"><a class="reference internal" href="../setup-sphinx.html">修改和构建本项目</a><input class="toctree-checkbox" id="toctree-checkbox-20" name="toctree-checkbox-20" role="switch" type="checkbox"/><label for="toctree-checkbox-20"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../rest-example.html">reStructuredText 基本语法</a><input class="toctree-checkbox" id="toctree-checkbox-21" name="toctree-checkbox-21" role="switch" type="checkbox"/><label for="toctree-checkbox-21"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
</aside>
<div class="main">
<div class="content">
<article role="main">
<div class="content-icon-container">
<div class="theme-toggle-container theme-toggle-content">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-content-icon" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
<div class="section" id="id1">
<h1>与进程有关的重要系统调用<a class="headerlink" href="#id1" title="永久链接至标题"></a></h1>
<div class="section" id="id2">
<h2>重要系统调用<a class="headerlink" href="#id2" title="永久链接至标题"></a></h2>
<div class="section" id="fork">
<h3>fork 系统调用<a class="headerlink" href="#fork" title="永久链接至标题"></a></h3>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="sd">/// 功能:由当前进程 fork 出一个子进程。</span>
<span class="sd">/// 返回值:对于子进程返回 0对于当前进程则返回子进程的 PID 。</span>
<span class="sd">/// syscall ID220</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sys_fork</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">isize</span><span class="p">;</span><span class="w"></span>
</pre></div>
</div>
</div>
<div class="section" id="exec">
<h3>exec 系统调用<a class="headerlink" href="#exec" title="永久链接至标题"></a></h3>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="sd">/// 功能:将当前进程的地址空间清空并加载一个特定的可执行文件,返回用户态后开始它的执行。</span>
<span class="sd">/// 参数:字符串 path 给出了要加载的可执行文件的名字;</span>
<span class="sd">/// 返回值:如果出错的话(如找不到名字相符的可执行文件)则返回 -1否则不应该返回。</span>
<span class="sd">/// 注意path 必须以 "\0" 结尾,否则内核将无法确定其长度</span>
<span class="sd">/// syscall ID221</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sys_exec</span><span class="p">(</span><span class="n">path</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">isize</span><span class="p">;</span><span class="w"></span>
</pre></div>
</div>
<p>利用 <code class="docutils literal notranslate"><span class="pre">fork</span></code><code class="docutils literal notranslate"><span class="pre">exec</span></code> 的组合,我们能让创建一个子进程,并令其执行特定的可执行文件。</p>
</div>
<div class="section" id="waitpid">
<h3>waitpid 系统调用<a class="headerlink" href="#waitpid" title="永久链接至标题"></a></h3>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="sd">/// 功能:当前进程等待一个子进程变为僵尸进程,回收其全部资源并收集其返回值。</span>
<span class="sd">/// 参数pid 表示要等待的子进程的进程 ID如果为 -1 的话表示等待任意一个子进程;</span>
<span class="sd">/// exit_code 表示保存子进程返回值的地址,如果这个地址为 0 的话表示不必保存。</span>
<span class="sd">/// 返回值:如果要等待的子进程不存在则返回 -1否则如果要等待的子进程均未结束则返回 -2</span>
<span class="sd">/// 否则返回结束的子进程的进程 ID。</span>
<span class="sd">/// syscall ID260</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sys_waitpid</span><span class="p">(</span><span class="n">pid</span>: <span class="kt">isize</span><span class="p">,</span><span class="w"> </span><span class="n">exit_code</span>: <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">isize</span><span class="p">;</span><span class="w"></span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">sys_waitpid</span></code> 在用户库中被封装成两个不同的 API <code class="docutils literal notranslate"><span class="pre">wait(exit_code:</span> <span class="pre">&amp;mut</span> <span class="pre">i32)</span></code><code class="docutils literal notranslate"><span class="pre">waitpid(pid:</span> <span class="pre">usize,</span> <span class="pre">exit_code:</span> <span class="pre">&amp;mut</span> <span class="pre">i32)</span></code>
前者用于等待任意一个子进程,后者用于等待特定子进程。它们实现的策略是如果子进程还未结束,就以 yield 让出时间片:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// user/src/lib.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">wait</span><span class="p">(</span><span class="n">exit_code</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">isize</span> <span class="p">{</span><span class="w"></span>
<span class="linenos"> 4</span><span class="w"> </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 5</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">sys_waitpid</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">exit_code</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">_</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 6</span><span class="w"> </span><span class="o">-</span><span class="mi">2</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">sys_yield</span><span class="p">();</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos"> 7</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos"> 8</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos"> 9</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">10</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="id3">
<h2>应用程序示例<a class="headerlink" href="#id3" title="永久链接至标题"></a></h2>
<p>借助这三个重要系统调用,我们可以开发功能更强大的应用。下面是两个案例: <strong>用户初始程序-init</strong><strong>shell程序-user_shell</strong></p>
<div class="section" id="initproc">
<h3>用户初始程序-initproc<a class="headerlink" href="#initproc" title="永久链接至标题"></a></h3>
<p>在内核初始化完毕后创建的第一个进程,是 <strong>用户初始进程</strong> (Initial Process) ,它将通过
<code class="docutils literal notranslate"><span class="pre">fork+exec</span></code> 创建 <code class="docutils literal notranslate"><span class="pre">user_shell</span></code> 子进程,并将被用于回收僵尸进程。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// user/src/bin/ch5b_initproc.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="cp">#![no_std]</span><span class="w"></span>
<span class="linenos"> 4</span><span class="cp">#![no_main]</span><span class="w"></span>
<span class="linenos"> 5</span>
<span class="linenos"> 6</span><span class="cp">#[macro_use]</span><span class="w"></span>
<span class="linenos"> 7</span><span class="k">extern</span><span class="w"> </span><span class="k">crate</span><span class="w"> </span><span class="n">user_lib</span><span class="p">;</span><span class="w"></span>
<span class="linenos"> 8</span>
<span class="linenos"> 9</span><span class="k">use</span><span class="w"> </span><span class="n">user_lib</span>::<span class="p">{</span><span class="w"></span>
<span class="linenos">10</span><span class="w"> </span><span class="n">fork</span><span class="p">,</span><span class="w"></span>
<span class="linenos">11</span><span class="w"> </span><span class="n">wait</span><span class="p">,</span><span class="w"></span>
<span class="linenos">12</span><span class="w"> </span><span class="n">exec</span><span class="p">,</span><span class="w"></span>
<span class="linenos">13</span><span class="w"> </span><span class="n">yield_</span><span class="p">,</span><span class="w"></span>
<span class="linenos">14</span><span class="p">};</span><span class="w"></span>
<span class="linenos">15</span>
<span class="linenos">16</span><span class="cp">#[no_mangle]</span><span class="w"></span>
<span class="linenos">17</span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">i32</span> <span class="p">{</span><span class="w"></span>
<span class="linenos">18</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">fork</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">19</span><span class="w"> </span><span class="n">exec</span><span class="p">(</span><span class="s">"ch5b_user_shell</span><span class="se">\0</span><span class="s">"</span><span class="p">);</span><span class="w"></span>
<span class="linenos">20</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">21</span><span class="w"> </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">22</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">exit_code</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="linenos">23</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">exit_code</span><span class="p">);</span><span class="w"></span>
<span class="linenos">24</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">25</span><span class="w"> </span><span class="n">yield_</span><span class="p">();</span><span class="w"></span>
<span class="linenos">26</span><span class="w"> </span><span class="k">continue</span><span class="p">;</span><span class="w"></span>
<span class="linenos">27</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">28</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="w"></span>
<span class="linenos">29</span><span class="w"> </span><span class="s">"[initproc] Released a zombie process, pid={}, exit_code={}"</span><span class="p">,</span><span class="w"></span>
<span class="linenos">30</span><span class="w"> </span><span class="n">pid</span><span class="p">,</span><span class="w"></span>
<span class="linenos">31</span><span class="w"> </span><span class="n">exit_code</span><span class="p">,</span><span class="w"></span>
<span class="linenos">32</span><span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="linenos">33</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">34</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">35</span><span class="w"> </span><span class="mi">0</span><span class="w"></span>
<span class="linenos">36</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<ul class="simple">
<li><p>第 19 行为 <code class="docutils literal notranslate"><span class="pre">fork</span></code> 出的子进程分支,通过 <code class="docutils literal notranslate"><span class="pre">exec</span></code> 启动shell程序 <code class="docutils literal notranslate"><span class="pre">user_shell</span></code>
注意我们需要在字符串末尾手动加入 <code class="docutils literal notranslate"><span class="pre">\0</span></code></p></li>
<li><p>第 21 行开始则为父进程分支,表示用户初始程序-initproc自身。它不断循环调用 <code class="docutils literal notranslate"><span class="pre">wait</span></code> 来等待并回收系统中的僵尸进程占据的资源。
如果回收成功的话则会打印一条报告信息给出被回收子进程的 PID 和返回值;否则就 <code class="docutils literal notranslate"><span class="pre">yield_</span></code> 交出 CPU 资源并在下次轮到它执行的时候再回收看看。</p></li>
</ul>
</div>
<div class="section" id="shell-user-shell">
<h3>shell程序-user_shell<a class="headerlink" href="#shell-user-shell" title="永久链接至标题"></a></h3>
<p>user_shell 需要捕获用户输入并进行解析处理,为此添加一个能获取用户输入的系统调用:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="sd">/// 功能:从文件中读取一段内容到缓冲区。</span>
<span class="sd">/// 参数fd 是待读取文件的文件描述符,切片 buffer 则给出缓冲区。</span>
<span class="sd">/// 返回值:如果出现了错误则返回 -1否则返回实际读到的字节数。</span>
<span class="sd">/// syscall ID63</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sys_read</span><span class="p">(</span><span class="n">fd</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">buffer</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span><span class="w"> </span>-&gt; <span class="kt">isize</span><span class="p">;</span><span class="w"></span>
</pre></div>
</div>
<p>实际调用时,我们必须要同时向内核提供缓冲区的起始地址及长度:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// user/src/syscall.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sys_read</span><span class="p">(</span><span class="n">fd</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">buffer</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="p">[</span><span class="kt">u8</span><span class="p">])</span><span class="w"> </span>-&gt; <span class="kt">isize</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">syscall</span><span class="p">(</span><span class="n">SYSCALL_READ</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="n">fd</span><span class="p">,</span><span class="w"> </span><span class="n">buffer</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">buffer</span><span class="p">.</span><span class="n">len</span><span class="p">()])</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>我们在用户库中将其进一步封装成每次能够从 <strong>标准输入</strong> 中获取一个字符的 <code class="docutils literal notranslate"><span class="pre">getchar</span></code> 函数。</p>
<p>shell程序 <code class="docutils literal notranslate"><span class="pre">user_shell</span></code> 实现如下:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// user/src/bin/ch5b_user_shell.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="cp">#![no_std]</span><span class="w"></span>
<span class="linenos"> 4</span><span class="cp">#![no_main]</span><span class="w"></span>
<span class="linenos"> 5</span>
<span class="linenos"> 6</span><span class="k">extern</span><span class="w"> </span><span class="k">crate</span><span class="w"> </span><span class="n">alloc</span><span class="p">;</span><span class="w"></span>
<span class="linenos"> 7</span>
<span class="linenos"> 8</span><span class="cp">#[macro_use]</span><span class="w"></span>
<span class="linenos"> 9</span><span class="k">extern</span><span class="w"> </span><span class="k">crate</span><span class="w"> </span><span class="n">user_lib</span><span class="p">;</span><span class="w"></span>
<span class="linenos">10</span>
<span class="linenos">11</span><span class="k">const</span><span class="w"> </span><span class="n">LF</span>: <span class="kt">u8</span> <span class="o">=</span><span class="w"> </span><span class="mh">0x0a</span><span class="k">u8</span><span class="p">;</span><span class="w"></span>
<span class="linenos">12</span><span class="k">const</span><span class="w"> </span><span class="n">CR</span>: <span class="kt">u8</span> <span class="o">=</span><span class="w"> </span><span class="mh">0x0d</span><span class="k">u8</span><span class="p">;</span><span class="w"></span>
<span class="linenos">13</span><span class="k">const</span><span class="w"> </span><span class="n">DL</span>: <span class="kt">u8</span> <span class="o">=</span><span class="w"> </span><span class="mh">0x7f</span><span class="k">u8</span><span class="p">;</span><span class="w"></span>
<span class="linenos">14</span><span class="k">const</span><span class="w"> </span><span class="n">BS</span>: <span class="kt">u8</span> <span class="o">=</span><span class="w"> </span><span class="mh">0x08</span><span class="k">u8</span><span class="p">;</span><span class="w"></span>
<span class="linenos">15</span>
<span class="linenos">16</span><span class="k">use</span><span class="w"> </span><span class="n">alloc</span>::<span class="n">string</span>::<span class="nb">String</span><span class="p">;</span><span class="w"></span>
<span class="linenos">17</span><span class="k">use</span><span class="w"> </span><span class="n">user_lib</span>::<span class="p">{</span><span class="n">fork</span><span class="p">,</span><span class="w"> </span><span class="n">exec</span><span class="p">,</span><span class="w"> </span><span class="n">waitpid</span><span class="p">,</span><span class="w"> </span><span class="n">yield_</span><span class="p">};</span><span class="w"></span>
<span class="linenos">18</span><span class="k">use</span><span class="w"> </span><span class="n">user_lib</span>::<span class="n">console</span>::<span class="n">getchar</span><span class="p">;</span><span class="w"></span>
<span class="linenos">19</span>
<span class="linenos">20</span><span class="cp">#[no_mangle]</span><span class="w"></span>
<span class="linenos">21</span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">i32</span> <span class="p">{</span><span class="w"></span>
<span class="linenos">22</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Rust user shell"</span><span class="p">);</span><span class="w"></span>
<span class="linenos">23</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">line</span>: <span class="nb">String</span> <span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="linenos">24</span><span class="w"> </span><span class="fm">print!</span><span class="p">(</span><span class="s">"&gt;&gt; "</span><span class="p">);</span><span class="w"></span>
<span class="linenos">25</span><span class="w"> </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">26</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">getchar</span><span class="p">();</span><span class="w"></span>
<span class="linenos">27</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="hll"><span class="linenos">28</span><span class="w"> </span><span class="n">LF</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">CR</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class="linenos">29</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">""</span><span class="p">);</span><span class="w"></span>
<span class="linenos">30</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">line</span><span class="p">.</span><span class="n">is_empty</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">31</span><span class="w"> </span><span class="n">line</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="sc">'\0'</span><span class="p">);</span><span class="w"></span>
<span class="linenos">32</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span><span class="w"></span>
<span class="linenos">33</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">34</span><span class="w"> </span><span class="c1">// child process</span>
<span class="linenos">35</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">exec</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">as_str</span><span class="p">())</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">36</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Error when executing!"</span><span class="p">);</span><span class="w"></span>
<span class="linenos">37</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="o">-</span><span class="mi">4</span><span class="p">;</span><span class="w"></span>
<span class="linenos">38</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">39</span><span class="w"> </span><span class="fm">unreachable!</span><span class="p">();</span><span class="w"></span>
<span class="linenos">40</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">41</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">exit_code</span>: <span class="kt">i32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="linenos">42</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">exit_pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">waitpid</span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">exit_code</span><span class="p">);</span><span class="w"></span>
<span class="linenos">43</span><span class="w"> </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span><span class="w"> </span><span class="n">exit_pid</span><span class="p">);</span><span class="w"></span>
<span class="linenos">44</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="w"></span>
<span class="linenos">45</span><span class="w"> </span><span class="s">"Shell: Process {} exited with code {}"</span><span class="p">,</span><span class="w"></span>
<span class="linenos">46</span><span class="w"> </span><span class="n">pid</span><span class="p">,</span><span class="w"> </span><span class="n">exit_code</span><span class="w"></span>
<span class="linenos">47</span><span class="w"> </span><span class="p">);</span><span class="w"></span>
<span class="linenos">48</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">49</span><span class="w"> </span><span class="n">line</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
<span class="linenos">50</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">51</span><span class="w"> </span><span class="fm">print!</span><span class="p">(</span><span class="s">"&gt;&gt; "</span><span class="p">);</span><span class="w"></span>
<span class="linenos">52</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="hll"><span class="linenos">53</span><span class="w"> </span><span class="n">BS</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">DL</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class="linenos">54</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">line</span><span class="p">.</span><span class="n">is_empty</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">55</span><span class="w"> </span><span class="fm">print!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">BS</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">char</span><span class="p">);</span><span class="w"></span>
<span class="linenos">56</span><span class="w"> </span><span class="fm">print!</span><span class="p">(</span><span class="s">" "</span><span class="p">);</span><span class="w"></span>
<span class="linenos">57</span><span class="w"> </span><span class="fm">print!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">BS</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">char</span><span class="p">);</span><span class="w"></span>
<span class="linenos">58</span><span class="w"> </span><span class="n">line</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span><span class="w"></span>
<span class="linenos">59</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">60</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="hll"><span class="linenos">61</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class="linenos">62</span><span class="w"> </span><span class="fm">print!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">char</span><span class="p">);</span><span class="w"></span>
<span class="linenos">63</span><span class="w"> </span><span class="n">line</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">char</span><span class="p">);</span><span class="w"></span>
<span class="linenos">64</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">65</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">66</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">67</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>可以看到,在以第 25 行开头的主循环中,每次都是调用 <code class="docutils literal notranslate"><span class="pre">getchar</span></code> 获取一个用户输入的字符,
并根据它相应进行一些动作。第 23 行声明的字符串 <code class="docutils literal notranslate"><span class="pre">line</span></code> 则维护着用户当前输入的命令内容,它也在不断发生变化。</p>
<ul>
<li><p>如果用户输入回车键(第 28 行那么user_shell 会 fork 出一个子进程(第 34 行开始)并试图通过
<code class="docutils literal notranslate"><span class="pre">exec</span></code> 系统调用执行一个应用,应用的名字在字符串 <code class="docutils literal notranslate"><span class="pre">line</span></code> 中给出。如果 exec 的返回值为 -1
说明在应用管理器中找不到对应名字的应用,此时子进程就直接打印错误信息并退出;否则子进程将开始执行目标应用。</p>
<p>fork 之后的 user_shell 进程自己的逻辑可以在第 41 行找到。它在等待 fork 出来的子进程结束并回收掉它的资源,还会顺带收集子进程的退出状态并打印出来。</p>
</li>
<li><p>如果用户输入退格键(第 53 行),首先我们需要将屏幕上当前行的最后一个字符用空格替换掉,
这可以通过输入一个特殊的退格字节 <code class="docutils literal notranslate"><span class="pre">BS</span></code> 来实现。其次user_shell 进程内维护的 <code class="docutils literal notranslate"><span class="pre">line</span></code> 也需要弹出最后一个字符。</p></li>
<li><p>如果用户输入了一个其他字符(第 61 行),就接将它打印在屏幕上,并加入到 <code class="docutils literal notranslate"><span class="pre">line</span></code> 中。</p></li>
<li><p>按键 <code class="docutils literal notranslate"><span class="pre">Ctrl+A</span></code> 再输入 <code class="docutils literal notranslate"><span class="pre">X</span></code> 来退出qemu模拟器。</p></li>
</ul>
</div>
</div>
</div>
</article>
<footer>
<div class="related-pages">
<a class="next-page" href="2core-data-structures.html">
<div class="page-info">
<div class="context">
<span>Next</span>
</div>
<div class="title">进程管理的核心数据结构</div>
</div>
<svg><use href="#svg-arrow-right"></use></svg>
</a>
<a class="prev-page" href="0intro.html">
<svg><use href="#svg-arrow-right"></use></svg>
<div class="page-info">
<div class="context">
<span>Previous</span>
</div>
<div class="title">引言</div>
</div>
</a>
</div>
<div class="related-information">
Copyright &#169; OS2022Summer
|
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a>
and
<a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
<a href="https://github.com/pradyunsg/furo">Furo theme</a>.
|
<a class="muted-link" href="../_sources/chapter5/1process.rst.txt"
rel="nofollow">
显示源代码
</a>
</div>
</footer>
</div>
<aside class="toc-drawer">
<div class="toc-sticky toc-scroll">
<div class="toc-title-container">
<span class="toc-title">
目录
</span>
</div>
<div class="toc-tree-container">
<div class="toc-tree">
<ul>
<li><a class="reference internal" href="#">与进程有关的重要系统调用</a><ul>
<li><a class="reference internal" href="#id2">重要系统调用</a><ul>
<li><a class="reference internal" href="#fork">fork 系统调用</a></li>
<li><a class="reference internal" href="#exec">exec 系统调用</a></li>
<li><a class="reference internal" href="#waitpid">waitpid 系统调用</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id3">应用程序示例</a><ul>
<li><a class="reference internal" href="#initproc">用户初始程序-initproc</a></li>
<li><a class="reference internal" href="#shell-user-shell">shell程序-user_shell</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</aside>
</div>
</div><script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/scripts/main.js"></script>
<script kind="utterances">
var commentsRunWhenDOMLoaded = cb => {
if (document.readyState != 'loading') {
cb()
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', cb)
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState == 'complete') cb()
})
}
}
var addUtterances = () => {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://utteranc.es/client.js";
script.async = "async";
script.setAttribute("repo", "LearningOS/rust-based-os-comp2022");
script.setAttribute("issue-term", "pathname");
script.setAttribute("theme", "github-light");
script.setAttribute("label", "comments");
script.setAttribute("crossorigin", "anonymous");
sections = document.querySelectorAll("div.section");
if (sections !== null) {
section = sections[sections.length-1];
section.appendChild(script);
}
}
commentsRunWhenDOMLoaded(addUtterances);
</script>
<script src="../_static/translations.js"></script>
</body>
</html>