Files
rust-based-os-comp2022/chapter1/4mini-rt-baremetal.html
2022-06-30 04:46:48 +00:00

658 lines
55 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="../chapter2/index.html" /><link rel="prev" title="构建用户态执行环境" href="3mini-rt-usrland.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 current has-children"><a class="reference internal" href="index.html">第一章:应用程序与基本执行环境</a><input checked="" 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 class="current">
<li class="toctree-l2"><a class="reference internal" href="0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="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="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="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 current has-children current-page"><a class="current reference internal" href="#">构建裸机执行环境</a><input checked="" 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 has-children"><a class="reference internal" href="../chapter5/index.html">第五章:进程及进程管理</a><input 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>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/1process.html">与进程有关的重要系统调用</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/2core-data-structures.html">进程管理的核心数据结构</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/3implement-process-mechanism.html">进程管理机制的设计实现</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter5/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="term-print-kernelminienv">
<span id="id1"></span><h1>构建裸机执行环境<a class="headerlink" href="#term-print-kernelminienv" title="永久链接至标题"></a></h1>
<div class="toctree-wrapper compound">
</div>
<p>有了上一节实现的用户态的最小执行环境,稍加改造,就可以完成裸机上的最小执行环境了。
本节中,我们将把 <code class="docutils literal notranslate"><span class="pre">Hello</span> <span class="pre">world!</span></code> 应用程序从用户态搬到内核态。</p>
<div class="section" id="id2">
<h2>裸机启动过程<a class="headerlink" href="#id2" title="永久链接至标题"></a></h2>
<p>用 QEMU 软件 <code class="docutils literal notranslate"><span class="pre">qemu-system-riscv64</span></code> 来模拟 RISC-V 64 计算机。加载内核程序的命令如下:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>qemu-system-riscv64 <span class="se">\</span>
-machine virt <span class="se">\</span>
-nographic <span class="se">\</span>
-bios <span class="k">$(</span>BOOTLOADER<span class="k">)</span> <span class="se">\</span>
-device loader,file<span class="o">=</span><span class="k">$(</span>KERNEL_BIN<span class="k">)</span>,addr<span class="o">=</span><span class="k">$(</span>KERNEL_ENTRY_PA<span class="k">)</span>
</pre></div>
</div>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">-bios</span> <span class="pre">$(BOOTLOADER)</span></code> 意味着硬件加载了一个 BootLoader 程序,即 RustSBI</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">-device</span> <span class="pre">loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA)</span></code> 表示硬件内存中的特定位置 <code class="docutils literal notranslate"><span class="pre">$(KERNEL_ENTRY_PA)</span></code> 放置了操作系统的二进制代码 <code class="docutils literal notranslate"><span class="pre">$(KERNEL_BIN)</span></code><code class="docutils literal notranslate"><span class="pre">$(KERNEL_ENTRY_PA)</span></code> 的值是 <code class="docutils literal notranslate"><span class="pre">0x80200000</span></code></p></li>
</ul>
<p>当我们执行包含上述启动参数的 qemu-system-riscv64 软件,就意味给这台虚拟的 RISC-V64 计算机加电了。
此时CPU 的其它通用寄存器清零,而 PC 会指向 <code class="docutils literal notranslate"><span class="pre">0x1000</span></code> 的位置,这里有固化在硬件中的一小段引导代码,
它会很快跳转到 <code class="docutils literal notranslate"><span class="pre">0x80000000</span></code> 的 RustSBI 处。
RustSBI完成硬件初始化后会跳转到 <code class="docutils literal notranslate"><span class="pre">$(KERNEL_BIN)</span></code> 所在内存位置 <code class="docutils literal notranslate"><span class="pre">0x80200000</span></code> 处,
执行操作系统的第一条指令。</p>
<div class="figure align-center">
<img alt="../_images/chap1-intro.png" src="../_images/chap1-intro.png"/>
</div>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p><strong>RustSBI 是什么?</strong></p>
<p>SBI 是 RISC-V 的一种底层规范RustSBI 是它的一种实现。
操作系统内核与 RustSBI 的关系有点像应用与操作系统内核的关系后者向前者提供一定的服务。只是SBI提供的服务很少
比如关机,显示字符串等。</p>
</div>
</div>
<div class="section" id="id3">
<h2>实现关机功能<a class="headerlink" href="#id3" title="永久链接至标题"></a></h2>
<p>对上一节实现的代码稍作调整,通过 <code class="docutils literal notranslate"><span class="pre">ecall</span></code> 调用 RustSBI 实现关机功能:</p>
<div class="highlight-rust notranslate" id="term-llvm-sbicall"><div class="highlight"><pre><span></span><span class="c1">// bootloader/rustsbi-qemu.bin 直接添加的SBI规范实现的二进制代码给操作系统提供基本支持服务</span>
<span class="c1">// os/src/sbi.rs</span>
<span class="k">fn</span> <span class="nf">sbi_call</span><span class="p">(</span><span class="n">which</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">arg0</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">arg1</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">arg2</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">usize</span> <span class="p">{</span><span class="w"></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">ret</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">core</span>::<span class="n">arch</span>::<span class="fm">asm!</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="s">"ecall"</span><span class="p">,</span><span class="w"></span>
<span class="o">..</span><span class="p">.</span><span class="w"></span>
<span class="k">const</span><span class="w"> </span><span class="n">SBI_SHUTDOWN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">8</span><span class="p">;</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">shutdown</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">sbi_call</span><span class="p">(</span><span class="n">SBI_SHUTDOWN</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="fm">panic!</span><span class="p">(</span><span class="s">"It should shutdown!"</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="c1">// os/src/main.rs</span>
<span class="cp">#[no_mangle]</span><span class="w"></span>
<span class="k">extern</span><span class="w"> </span><span class="s">"C"</span><span class="w"> </span><span class="k">fn</span> <span class="nf">_start</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">shutdown</span><span class="p">();</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>应用程序访问操作系统提供的系统调用的指令是 <code class="docutils literal notranslate"><span class="pre">ecall</span></code> ,操作系统访问
RustSBI提供的SBI调用的指令也是 <code class="docutils literal notranslate"><span class="pre">ecall</span></code>
虽然指令一样,但它们所在的特权级是不一样的。
简单地说应用程序位于最弱的用户特权级User Mode
操作系统位于内核特权级Supervisor Mode
RustSBI位于机器特权级Machine Mode
下一章会进一步阐释具体细节。</p>
<p>编译执行,结果如下:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="c1"># 编译生成ELF格式的执行文件</span>
$ cargo build --release
Compiling os v0.1.0 <span class="o">(</span>/media/chyyuu/ca8c7ba6-51b7-41fc-8430-e29e31e5328f/thecode/rust/os_kernel_lab/os<span class="o">)</span>
Finished release <span class="o">[</span>optimized<span class="o">]</span> target<span class="o">(</span>s<span class="o">)</span> <span class="k">in</span> <span class="m">0</span>.15s
<span class="c1"># 把ELF执行文件转成bianary文件</span>
$ rust-objcopy --binary-architecture<span class="o">=</span>riscv64 target/riscv64gc-unknown-none-elf/release/os --strip-all -O binary target/riscv64gc-unknown-none-elf/release/os.bin
<span class="c1"># 加载运行</span>
$ qemu-system-riscv64 -machine virt -nographic -bios ../bootloader/rustsbi-qemu.bin -device loader,file<span class="o">=</span>target/riscv64gc-unknown-none-elf/release/os.bin,addr<span class="o">=</span>0x80200000
<span class="c1"># 无法退出,风扇狂转,感觉碰到死循环</span>
</pre></div>
</div>
<p>问题在哪?通过 rust-readobj 分析 <code class="docutils literal notranslate"><span class="pre">os</span></code> 可执行程序,发现其入口地址不是
RustSBI 约定的 <code class="docutils literal notranslate"><span class="pre">0x80200000</span></code> 。我们需要修改程序的内存布局并设置好栈空间。</p>
</div>
<div class="section" id="id4">
<h2>设置正确的程序内存布局<a class="headerlink" href="#id4" title="永久链接至标题"></a></h2>
<p>可以通过 <strong>链接脚本</strong> (Linker Script) 调整链接器的行为,使得最终生成的可执行文件的内存布局符合我们的预期。</p>
<p>修改 Cargo 的配置文件来使用我们自己的链接脚本 <code class="docutils literal notranslate"><span class="pre">os/src/linker.ld</span></code></p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="o">//</span> <span class="n">os</span><span class="o">/.</span><span class="n">cargo</span><span class="o">/</span><span class="n">config</span>
<span class="linenos">2</span><span class="p">[</span><span class="n">build</span><span class="p">]</span>
<span class="linenos">3</span><span class="n">target</span> <span class="o">=</span> <span class="s2">"riscv64gc-unknown-none-elf"</span>
<span class="linenos">4</span>
<span class="hll"><span class="linenos">5</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">riscv64gc</span><span class="o">-</span><span class="n">unknown</span><span class="o">-</span><span class="n">none</span><span class="o">-</span><span class="n">elf</span><span class="p">]</span>
</span><span class="hll"><span class="linenos">6</span><span class="n">rustflags</span> <span class="o">=</span> <span class="p">[</span>
</span><span class="hll"><span class="linenos">7</span> <span class="s2">"-Clink-arg=-Tsrc/linker.ld"</span><span class="p">,</span> <span class="s2">"-Cforce-frame-pointers=yes"</span>
</span><span class="hll"><span class="linenos">8</span><span class="p">]</span>
</span></pre></div>
</div>
<p>具体的链接脚本 <code class="docutils literal notranslate"><span class="pre">os/src/linker.ld</span></code> 如下:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="n">OUTPUT_ARCH</span><span class="p">(</span><span class="n">riscv</span><span class="p">)</span>
<span class="linenos"> 2</span><span class="n">ENTRY</span><span class="p">(</span><span class="n">_start</span><span class="p">)</span>
<span class="linenos"> 3</span><span class="n">BASE_ADDRESS</span> <span class="o">=</span> <span class="mh">0x80200000</span><span class="p">;</span>
<span class="linenos"> 4</span>
<span class="linenos"> 5</span><span class="n">SECTIONS</span>
<span class="linenos"> 6</span><span class="p">{</span>
<span class="linenos"> 7</span> <span class="o">.</span> <span class="o">=</span> <span class="n">BASE_ADDRESS</span><span class="p">;</span>
<span class="linenos"> 8</span> <span class="n">skernel</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos"> 9</span>
<span class="linenos">10</span> <span class="n">stext</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">11</span> <span class="o">.</span><span class="n">text</span> <span class="p">:</span> <span class="p">{</span>
<span class="linenos">12</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">text</span><span class="o">.</span><span class="n">entry</span><span class="p">)</span>
<span class="linenos">13</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">text</span> <span class="o">.</span><span class="n">text</span><span class="o">.*</span><span class="p">)</span>
<span class="linenos">14</span> <span class="p">}</span>
<span class="linenos">15</span>
<span class="linenos">16</span> <span class="o">.</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="mi">4</span><span class="n">K</span><span class="p">);</span>
<span class="linenos">17</span> <span class="n">etext</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">18</span> <span class="n">srodata</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">19</span> <span class="o">.</span><span class="n">rodata</span> <span class="p">:</span> <span class="p">{</span>
<span class="linenos">20</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">rodata</span> <span class="o">.</span><span class="n">rodata</span><span class="o">.*</span><span class="p">)</span>
<span class="linenos">21</span> <span class="p">}</span>
<span class="linenos">22</span>
<span class="linenos">23</span> <span class="o">.</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="mi">4</span><span class="n">K</span><span class="p">);</span>
<span class="linenos">24</span> <span class="n">erodata</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">25</span> <span class="n">sdata</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">26</span> <span class="o">.</span><span class="n">data</span> <span class="p">:</span> <span class="p">{</span>
<span class="linenos">27</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">data</span> <span class="o">.</span><span class="n">data</span><span class="o">.*</span><span class="p">)</span>
<span class="linenos">28</span> <span class="p">}</span>
<span class="linenos">29</span>
<span class="linenos">30</span> <span class="o">.</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="mi">4</span><span class="n">K</span><span class="p">);</span>
<span class="linenos">31</span> <span class="n">edata</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">32</span> <span class="o">.</span><span class="n">bss</span> <span class="p">:</span> <span class="p">{</span>
<span class="linenos">33</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">bss</span><span class="o">.</span><span class="n">stack</span><span class="p">)</span>
<span class="linenos">34</span> <span class="n">sbss</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">35</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">bss</span> <span class="o">.</span><span class="n">bss</span><span class="o">.*</span><span class="p">)</span>
<span class="linenos">36</span> <span class="p">}</span>
<span class="linenos">37</span>
<span class="linenos">38</span> <span class="o">.</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="mi">4</span><span class="n">K</span><span class="p">);</span>
<span class="linenos">39</span> <span class="n">ebss</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">40</span> <span class="n">ekernel</span> <span class="o">=</span> <span class="o">.</span><span class="p">;</span>
<span class="linenos">41</span>
<span class="linenos">42</span> <span class="o">/</span><span class="n">DISCARD</span><span class="o">/</span> <span class="p">:</span> <span class="p">{</span>
<span class="linenos">43</span> <span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="n">eh_frame</span><span class="p">)</span>
<span class="linenos">44</span> <span class="p">}</span>
<span class="linenos">45</span><span class="p">}</span>
</pre></div>
</div>
<p>第 1 行我们设置了目标平台为 riscv ;第 2 行我们设置了整个程序的入口点为之前定义的全局符号 <code class="docutils literal notranslate"><span class="pre">_start</span></code>
第 3 行定义了一个常量 <code class="docutils literal notranslate"><span class="pre">BASE_ADDRESS</span></code><code class="docutils literal notranslate"><span class="pre">0x80200000</span></code> RustSBI 期望的 OS 起始地址;</p>
<div class="admonition attention">
<p class="admonition-title">注意</p>
<p>linker 脚本的语法不做要求,感兴趣的同学可以自行查阅相关资料。</p>
</div>
<p><code class="docutils literal notranslate"><span class="pre">BASE_ADDRESS</span></code> 开始,代码段 <code class="docutils literal notranslate"><span class="pre">.text</span></code>, 只读数据段 <code class="docutils literal notranslate"><span class="pre">.rodata</span></code>,数据段 <code class="docutils literal notranslate"><span class="pre">.data</span></code>, bss 段 <code class="docutils literal notranslate"><span class="pre">.bss</span></code> 由低到高依次放置,
且每个段都有两个全局变量给出其起始和结束地址(比如 <code class="docutils literal notranslate"><span class="pre">.text</span></code> 段的开始和结束地址分别是 <code class="docutils literal notranslate"><span class="pre">stext</span></code><code class="docutils literal notranslate"><span class="pre">etext</span></code> )。</p>
</div>
<div class="section" id="id5">
<h2>正确配置栈空间布局<a class="headerlink" href="#id5" title="永久链接至标题"></a></h2>
<p>用另一段汇编代码初始化栈空间:</p>
<div class="highlight-asm notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1"># os/src/entry.asm</span>
<span class="linenos"> 2</span> <span class="na">.section</span> <span class="no">.text.entry</span>
<span class="linenos"> 3</span> <span class="na">.globl</span> <span class="no">_start</span>
<span class="linenos"> 4</span><span class="nl">_start:</span>
<span class="linenos"> 5</span> <span class="nf">la</span> <span class="no">sp</span><span class="p">,</span> <span class="no">boot_stack_top</span>
<span class="linenos"> 6</span> <span class="nf">call</span> <span class="no">rust_main</span>
<span class="linenos"> 7</span>
<span class="linenos"> 8</span> <span class="na">.section</span> <span class="no">.bss.stack</span>
<span class="linenos"> 9</span> <span class="na">.globl</span> <span class="no">boot_stack</span>
<span class="linenos">10</span><span class="nl">boot_stack:</span>
<span class="linenos">11</span> <span class="na">.space</span> <span class="mi">4096</span> <span class="p">*</span> <span class="mi">16</span>
<span class="linenos">12</span> <span class="na">.globl</span> <span class="no">boot_stack_top</span>
<span class="linenos">13</span><span class="nl">boot_stack_top:</span>
</pre></div>
</div>
<p>在第 8 行,我们预留了一块大小为 4096 * 16 字节,也就是 <span class="math notranslate nohighlight">\(64\text{KiB}\)</span> 的空间,
用作操作系统的栈空间。
栈顶地址被全局符号 <code class="docutils literal notranslate"><span class="pre">boot_stack_top</span></code> 标识,栈底则被全局符号 <code class="docutils literal notranslate"><span class="pre">boot_stack</span></code> 标识。
同时,这块栈空间被命名为
<code class="docutils literal notranslate"><span class="pre">.bss.stack</span></code> ,链接脚本里有它的位置。</p>
<p><code class="docutils literal notranslate"><span class="pre">_start</span></code> 作为操作系统的入口地址,将依据链接脚本被放在 <code class="docutils literal notranslate"><span class="pre">BASE_ADDRESS</span></code> 处。
<code class="docutils literal notranslate"><span class="pre">la</span> <span class="pre">sp,</span> <span class="pre">boot_stack_top</span></code> 作为 OS 的第一条指令,
将 sp 设置为栈空间的栈顶。
简单起见,我们目前不考虑 sp 越过栈底 <code class="docutils literal notranslate"><span class="pre">boot_stack</span></code> ,也就是栈溢出的情形。
第二条指令则是函数调用 <code class="docutils literal notranslate"><span class="pre">rust_main</span></code> ,这里的 <code class="docutils literal notranslate"><span class="pre">rust_main</span></code> 是我们稍后自己编写的应用入口。</p>
<p>接着,我们在 <code class="docutils literal notranslate"><span class="pre">main.rs</span></code> 中嵌入这些汇编代码并声明应用入口 <code class="docutils literal notranslate"><span class="pre">rust_main</span></code> </p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// os/src/main.rs</span>
<span class="linenos"> 2</span><span class="cp">#![no_std]</span><span class="w"></span>
<span class="linenos"> 3</span><span class="cp">#![no_main]</span><span class="w"></span>
<span class="linenos"> 4</span>
<span class="linenos"> 5</span><span class="k">mod</span> <span class="nn">lang_items</span><span class="p">;</span><span class="w"></span>
<span class="linenos"> 6</span>
<span class="hll"><span class="linenos"> 7</span><span class="n">core</span>::<span class="n">arch</span>::<span class="fm">global_asm!</span><span class="p">(</span><span class="fm">include_str!</span><span class="p">(</span><span class="s">"entry.asm"</span><span class="p">));</span><span class="w"></span>
</span><span class="linenos"> 8</span>
<span class="hll"><span class="linenos"> 9</span><span class="cp">#[no_mangle]</span><span class="w"></span>
</span><span class="hll"><span class="linenos">10</span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">rust_main</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class="hll"><span class="linenos">11</span><span class="w"> </span><span class="n">shutdown</span><span class="p">();</span><span class="w"></span>
</span><span class="hll"><span class="linenos">12</span><span class="p">}</span><span class="w"></span>
</span></pre></div>
</div>
<p>背景高亮指出了 <code class="docutils literal notranslate"><span class="pre">main.rs</span></code> 中新增的代码。</p>
<p>第 7 行,我们使用 <code class="docutils literal notranslate"><span class="pre">global_asm</span></code> 宏,将同目录下的汇编文件 <code class="docutils literal notranslate"><span class="pre">entry.asm</span></code> 嵌入到代码中。</p>
<p>从第 9 行开始,
我们声明了应用的入口点 <code class="docutils literal notranslate"><span class="pre">rust_main</span></code> ,需要注意的是,这里通过宏将 <code class="docutils literal notranslate"><span class="pre">rust_main</span></code>
标记为 <code class="docutils literal notranslate"><span class="pre">#[no_mangle]</span></code> 以避免编译器对它的名字进行混淆,不然在链接时,
<code class="docutils literal notranslate"><span class="pre">entry.asm</span></code> 将找不到 <code class="docutils literal notranslate"><span class="pre">main.rs</span></code> 提供的外部符号 <code class="docutils literal notranslate"><span class="pre">rust_main</span></code>,导致链接失败。</p>
<p>再次使用上节中的编译生成和运行操作我们看到QEMU模拟的RISC-V 64计算机 <strong>优雅</strong> 地退出了!</p>
</div>
<div class="section" id="bss">
<h2>清空 .bss 段<a class="headerlink" href="#bss" title="永久链接至标题"></a></h2>
<p>等一等,与内存相关的部分太容易出错了, <strong>清零 .bss 段</strong> 的工作我们还没有完成。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// os/src/main.rs</span>
<span class="linenos"> 2</span><span class="k">fn</span> <span class="nf">clear_bss</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 3</span><span class="w"> </span><span class="k">extern</span><span class="w"> </span><span class="s">"C"</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 4</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sbss</span><span class="p">();</span><span class="w"></span>
<span class="linenos"> 5</span><span class="w"> </span><span class="k">fn</span> <span class="nf">ebss</span><span class="p">();</span><span class="w"></span>
<span class="linenos"> 6</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos"> 7</span><span class="w"> </span><span class="p">(</span><span class="n">sbss</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="o">..</span><span class="n">ebss</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="n">for_each</span><span class="p">(</span><span class="o">|</span><span class="n">a</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 8</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="n">a</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="kt">u8</span><span class="p">).</span><span class="n">write_volatile</span><span class="p">(</span><span class="mi">0</span><span class="p">)</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>
<span class="linenos">11</span>
<span class="linenos">12</span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">rust_main</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">13</span><span class="w"> </span><span class="n">clear_bss</span><span class="p">();</span><span class="w"></span>
<span class="linenos">14</span><span class="w"> </span><span class="n">shutdown</span><span class="p">();</span><span class="w"></span>
<span class="linenos">15</span><span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>链接脚本 <code class="docutils literal notranslate"><span class="pre">linker.ld</span></code> 中给出的全局符号 <code class="docutils literal notranslate"><span class="pre">sbss</span></code><code class="docutils literal notranslate"><span class="pre">ebss</span></code> 让我们能轻松确定 <code class="docutils literal notranslate"><span class="pre">.bss</span></code> 段的位置。</p>
</div>
<div class="section" id="id6">
<h2>添加裸机打印相关函数<a class="headerlink" href="#id6" title="永久链接至标题"></a></h2>
<p>在上一节中我们为用户态程序实现的 <code class="docutils literal notranslate"><span class="pre">println</span></code> 宏,略作修改即可用于本节的内核态操作系统。
详见 <code class="docutils literal notranslate"><span class="pre">os/src/console.rs</span></code></p>
<p>利用 <code class="docutils literal notranslate"><span class="pre">println</span></code> 宏,我们重写异常处理函数 <code class="docutils literal notranslate"><span class="pre">panic</span></code>,使其在 panic 时能打印错误发生的位置。
相关代码位于 <code class="docutils literal notranslate"><span class="pre">os/src/lang_items.rs</span></code> 中。</p>
<p>我们还使用第三方库 <code class="docutils literal notranslate"><span class="pre">log</span></code> 为你实现了日志模块,相关代码位于 <code class="docutils literal notranslate"><span class="pre">os/src/logging.rs</span></code> 中。</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>在 cargo 项目中引入外部库 log需要修改 <code class="docutils literal notranslate"><span class="pre">Cargo.toml</span></code> 加入相应的依赖信息。</p>
</div>
<p>现在,让我们重复一遍本章开头的试验,<code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">run</span> <span class="pre">LOG=TRACE</span></code></p>
<div class="figure align-center">
<img alt="../_images/color-demo.png" src="../_images/color-demo.png"/>
</div>
<p>产生 panic 的地点与源码中的实际位置一致!至此,我们完成了第一章的实验内容,</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>背景知识:<a class="reference external" href="https://rcore-os.github.io/rCore-Tutorial-Book-v3/chapter1/4understand-prog.html">理解应用程序和执行环境</a></p>
</div>
</div>
</div>
</article>
<footer>
<div class="related-pages">
<a class="next-page" href="../chapter2/index.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="3mini-rt-usrland.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/chapter1/4mini-rt-baremetal.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></li>
<li><a class="reference internal" href="#id3">实现关机功能</a></li>
<li><a class="reference internal" href="#id4">设置正确的程序内存布局</a></li>
<li><a class="reference internal" href="#id5">正确配置栈空间布局</a></li>
<li><a class="reference internal" href="#bss">清空 .bss 段</a></li>
<li><a class="reference internal" href="#id6">添加裸机打印相关函数</a></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>
<script async="async" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
</body>
</html>