mirror of
https://github.com/LearningOS/rust-based-os-comp2022.git
synced 2026-05-05 20:59:48 +08:00
658 lines
55 KiB
HTML
658 lines
55 KiB
HTML
<!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">附录 A:Rust 系统编程资料</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">附录 D:RISC-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>-> <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>-> <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>-> <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>-> <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 © 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> |