Files
rust-based-os-comp2022/chapter6/3using-easy-fs-in-kernel.html
2022-06-30 04:46:48 +00:00

682 lines
74 KiB
HTML
Raw 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="chapter6练习" href="4exercise.html" /><link rel="prev" title="简易文件系统 easy-fs (下)" href="2fs-implementation-2.html" />
<meta name="generator" content="sphinx-4.1.2, furo 2021.08.31"/>
<title>在内核中使用 easy-fs - Open-Source-OS-Training-Camp-2022 文档</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=c7c65a82b42f6b978e58466c1e9ef2509836d916" />
<link rel="stylesheet" type="text/css" href="../_static/tabs.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo-extensions.css?digest=16fb25fabf47304eee183a5e9af80b1ba98259b1" />
<link rel="stylesheet" type="text/css" href="../_static/my_style.css" />
<style>
body {
--color-code-background: #f8f8f8;
--color-code-foreground: black;
}
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
}
</style></head>
<body>
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-toc" viewBox="0 0 24 24">
<title>Contents</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" />
<line x1="4" y1="6" x2="20" y2="6" />
<line x1="10" y1="12" x2="20" y2="12" />
<line x1="6" y1="18" x2="20" y2="18" />
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24">
<title>Light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24">
<title>Dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
</symbol>
<symbol id="svg-sun-half" viewBox="0 0 24 24">
<title>Auto light/dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="9" />
<path d="M13 12h5" />
<path d="M13 15h4" />
<path d="M13 18h1" />
<path d="M13 9h4" />
<path d="M13 6h1" />
</svg>
</symbol>
</svg>
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
<label class="overlay sidebar-overlay" for="__navigation">
<div class="visually-hidden">Hide navigation sidebar</div>
</label>
<label class="overlay toc-overlay" for="__toc">
<div class="visually-hidden">Hide table of contents sidebar</div>
</label>
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<div class="visually-hidden">Toggle site navigation sidebar</div>
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
</label>
</div>
<div class="header-center">
<a href="../index.html"><div class="brand">Open-Source-OS-Training-Camp-2022 文档</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
<span class="sidebar-brand-text">Open-Source-OS-Training-Camp-2022 文档</span>
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
<input class="sidebar-search" placeholder=搜索 name="q" aria-label="搜索">
<input type="hidden" name="check_keywords" value="yes">
<input type="hidden" name="area" value="default">
</form>
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
<p class="caption" role="heading"><span class="caption-text">正文</span></p>
<ul class="current">
<li class="toctree-l1 has-children"><a class="reference internal" href="../0setup-devel-env.html">第零章:实验环境配置</a><input class="toctree-checkbox" id="toctree-checkbox-1" name="toctree-checkbox-1" role="switch" type="checkbox"/><label for="toctree-checkbox-1"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter1/index.html">第一章:应用程序与基本执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-2" name="toctree-checkbox-2" role="switch" type="checkbox"/><label for="toctree-checkbox-2"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter1/0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/1app-ee-platform.html">应用程序执行环境与平台支持</a><input class="toctree-checkbox" id="toctree-checkbox-3" name="toctree-checkbox-3" role="switch" type="checkbox"/><label for="toctree-checkbox-3"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/2remove-std.html">移除标准库依赖</a><input class="toctree-checkbox" id="toctree-checkbox-4" name="toctree-checkbox-4" role="switch" type="checkbox"/><label for="toctree-checkbox-4"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/3mini-rt-usrland.html">构建用户态执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-5" name="toctree-checkbox-5" role="switch" type="checkbox"/><label for="toctree-checkbox-5"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter1/4mini-rt-baremetal.html">构建裸机执行环境</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter2/index.html">第二章:批处理系统</a><input class="toctree-checkbox" id="toctree-checkbox-7" name="toctree-checkbox-7" role="switch" type="checkbox"/><label for="toctree-checkbox-7"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter2/0intro.html">引言</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/2application.html">实现应用程序</a><input class="toctree-checkbox" id="toctree-checkbox-8" name="toctree-checkbox-8" role="switch" type="checkbox"/><label for="toctree-checkbox-8"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/3batch-system.html">实现批处理操作系统</a><input class="toctree-checkbox" id="toctree-checkbox-9" name="toctree-checkbox-9" role="switch" type="checkbox"/><label for="toctree-checkbox-9"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../chapter2/4trap-handling.html">实现特权级的切换</a><input class="toctree-checkbox" id="toctree-checkbox-10" name="toctree-checkbox-10" role="switch" type="checkbox"/><label for="toctree-checkbox-10"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter3/index.html">第三章:多道程序与分时多任务</a><input class="toctree-checkbox" id="toctree-checkbox-11" name="toctree-checkbox-11" role="switch" type="checkbox"/><label for="toctree-checkbox-11"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/1multi-loader.html">多道程序放置与加载</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/2task-switching.html">任务切换</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/3multiprogramming.html">管理多道程序</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/4time-sharing-system.html">分时多任务系统</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter3/5exercise.html">chapter3练习</a></li>
</ul>
</li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../chapter4/index.html">第四章:地址空间</a><input class="toctree-checkbox" id="toctree-checkbox-12" name="toctree-checkbox-12" role="switch" type="checkbox"/><label for="toctree-checkbox-12"><div class="visually-hidden">Toggle child pages in navigation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/3sv39-implementation-1.html">实现 SV39 多级页表机制(上)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/4sv39-implementation-2.html">实现 SV39 多级页表机制(下)</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/5kernel-app-spaces.html">内核与应用的地址空间</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/6multitasking-based-on-as.html">基于地址空间的分时多任务</a></li>
<li class="toctree-l2"><a class="reference internal" href="../chapter4/7exercise.html">chapter4练习</a></li>
</ul>
</li>
<li class="toctree-l1 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 current has-children"><a class="reference internal" href="index.html">第六章文件系统与I/O重定向</a><input checked="" 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 class="current">
<li class="toctree-l2"><a class="reference internal" href="0intro.html">引言</a></li>
<li class="toctree-l2"><a class="reference internal" href="1file-descriptor.html">文件与文件描述符</a></li>
<li class="toctree-l2"><a class="reference internal" href="1fs-interface.html">文件系统接口</a></li>
<li class="toctree-l2"><a class="reference internal" href="2fs-implementation-1.html">简易文件系统 easy-fs (上)</a></li>
<li class="toctree-l2"><a class="reference internal" href="2fs-implementation-2.html">简易文件系统 easy-fs (下)</a></li>
<li class="toctree-l2 current current-page"><a class="current reference internal" href="#">在内核中使用 easy-fs</a></li>
<li class="toctree-l2"><a class="reference internal" href="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="easy-fs">
<h1>在内核中使用 easy-fs<a class="headerlink" href="#easy-fs" title="永久链接至标题"></a></h1>
<div class="section" id="id1">
<h2>块设备驱动层<a class="headerlink" href="#id1" title="永久链接至标题"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">drivers</span></code> 子模块中的 <code class="docutils literal notranslate"><span class="pre">block/mod.rs</span></code> 中,我们可以找到内核访问的块设备实例 <code class="docutils literal notranslate"><span class="pre">BLOCK_DEVICE</span></code> </p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/drivers/block/mod.rs</span>
<span class="k">type</span> <span class="nc">BlockDeviceImpl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">virtio_blk</span>::<span class="n">VirtIOBlock</span><span class="p">;</span><span class="w"></span>
<span class="n">lazy_static</span><span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">ref</span><span class="w"> </span><span class="n">BLOCK_DEVICE</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">BlockDeviceImpl</span>::<span class="n">new</span><span class="p">());</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>在 qemu 上,我们使用 <code class="docutils literal notranslate"><span class="pre">VirtIOBlock</span></code> 访问 VirtIO 块设备,并将它全局实例化为 <code class="docutils literal notranslate"><span class="pre">BLOCK_DEVICE</span></code> ,使内核的其他模块可以访问。</p>
<p>在启动 Qemu 模拟器的时候,我们可以配置参数来添加一块 VirtIO 块设备:</p>
<div class="highlight-makefile notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c"># os/Makefile</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="nv">FS_IMG</span> <span class="o">:=</span> ../user/target/<span class="k">$(</span>TARGET<span class="k">)</span>/<span class="k">$(</span>MODE<span class="k">)</span>/fs.img
<span class="linenos"> 4</span>
<span class="linenos"> 5</span><span class="nf">run</span><span class="o">:</span> <span class="n">build</span>
<span class="linenos"> 6</span> @qemu-system-riscv64 <span class="se">\</span>
<span class="linenos"> 7</span> -machine virt <span class="se">\</span>
<span class="linenos"> 8</span> -nographic <span class="se">\</span>
<span class="linenos"> 9</span> -bios <span class="k">$(</span>BOOTLOADER<span class="k">)</span> <span class="se">\</span>
<span class="linenos">10</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> <span class="se">\</span>
<span class="hll"><span class="linenos">11</span> -drive <span class="nv">file</span><span class="o">=</span><span class="k">$(</span>FS_IMG<span class="k">)</span>,if<span class="o">=</span>none,format<span class="o">=</span>raw,id<span class="o">=</span>x0 <span class="se">\</span>
</span><span class="hll"><span class="linenos">12</span> -device virtio-blk-device,drive<span class="o">=</span>x0,bus<span class="o">=</span>virtio-mmio-bus.0
</span></pre></div>
</div>
<ul class="simple">
<li><p>第 11 行,我们为虚拟机添加一块虚拟硬盘,内容为我们之前通过 <code class="docutils literal notranslate"><span class="pre">easy-fs-fuse</span></code> 工具打包的包含应用 ELF 的 easy-fs 镜像,并命名为 <code class="docutils literal notranslate"><span class="pre">x0</span></code></p></li>
<li><p>第 12 行,我们将硬盘 <code class="docutils literal notranslate"><span class="pre">x0</span></code> 作为一个 VirtIO 总线中的一个块设备接入到虚拟机系统中。 <code class="docutils literal notranslate"><span class="pre">virtio-mmio-bus.0</span></code> 表示 VirtIO 总线通过 MMIO 进行控制,且该块设备在总线中的编号为 0 。</p></li>
</ul>
<p><strong>内存映射 I/O</strong> (MMIO, Memory-Mapped I/O) 指通过特定的物理内存地址来访问外设的设备寄存器。查阅资料,可知 VirtIO 总线的 MMIO 物理地址区间为从 0x10001000 开头的 4KiB 。</p>
<p><code class="docutils literal notranslate"><span class="pre">config</span></code> 子模块中我们硬编码 Qemu 上的 VirtIO 总线的 MMIO 地址区间(起始地址,长度)。在创建内核地址空间的时候需要建立页表映射:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/config.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">MMIO</span>: <span class="kp">&amp;</span><span class="p">[(</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="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="p">[</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="mh">0x10001000</span><span class="p">,</span><span class="w"> </span><span class="mh">0x1000</span><span class="p">),</span><span class="w"></span>
<span class="p">];</span><span class="w"></span>
<span class="c1">// os/src/mm/memory_set.rs</span>
<span class="k">use</span><span class="w"> </span><span class="k">crate</span>::<span class="n">config</span>::<span class="n">MMIO</span><span class="p">;</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">MemorySet</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="sd">/// Without kernel stacks.</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">new_kernel</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"></span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"mapping memory-mapped registers"</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">pair</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">MMIO</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">memory_set</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">MapArea</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">pair</span><span class="p">).</span><span class="mf">0.</span><span class="n">into</span><span class="p">(),</span><span class="w"></span>
<span class="w"> </span><span class="p">((</span><span class="o">*</span><span class="n">pair</span><span class="p">).</span><span class="mi">0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">pair</span><span class="p">).</span><span class="mi">1</span><span class="p">).</span><span class="n">into</span><span class="p">(),</span><span class="w"></span>
<span class="w"> </span><span class="n">MapType</span>::<span class="n">Identical</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">MapPermission</span>::<span class="n">R</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">MapPermission</span>::<span class="n">W</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">),</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">memory_set</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>这里我们进行的是透明的恒等映射,让内核可以兼容于直接访问物理地址的设备驱动库。</p>
<p>由于设备驱动的开发过程比较琐碎,我们这里直接使用已有的 <a class="reference external" href="https://github.com/rcore-os/virtio-drivers">virtio-drivers</a> crate感兴趣的同学可以自行了解。</p>
</div>
<div class="section" id="id2">
<h2>内核索引节点层<a class="headerlink" href="#id2" title="永久链接至标题"></a></h2>
<p>内核将 <code class="docutils literal notranslate"><span class="pre">easy-fs</span></code> 提供的 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 进一步封装为 OS 中的索引节点 <code class="docutils literal notranslate"><span class="pre">OSInode</span></code></p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/fs/inode.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">OSInode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">readable</span>: <span class="kt">bool</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">writable</span>: <span class="kt">bool</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inner</span>: <span class="nc">UPSafeCell</span><span class="o">&lt;</span><span class="n">OSInodeInner</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">OSInodeInner</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">offset</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inode</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Inode</span><span class="o">&gt;</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">OSInode</span></code> 就表示进程中一个被打开的常规文件或目录。 <code class="docutils literal notranslate"><span class="pre">readable/writable</span></code> 分别表明该文件是否允许通过 <code class="docutils literal notranslate"><span class="pre">sys_read/write</span></code> 进行读写,读写过程中的偏移量 <code class="docutils literal notranslate"><span class="pre">offset</span></code><code class="docutils literal notranslate"><span class="pre">Inode</span></code> 则加上互斥锁丢到 <code class="docutils literal notranslate"><span class="pre">OSInodeInner</span></code> 中。</p>
</div>
<div class="section" id="id3">
<h2>文件描述符层<a class="headerlink" href="#id3" title="永久链接至标题"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">OSInode</span></code> 也是要一种要放到进程文件描述符表中,通过 <code class="docutils literal notranslate"><span class="pre">sys_read/write</span></code> 进行读写的文件,我们需要为它实现 <code class="docutils literal notranslate"><span class="pre">File</span></code> Trait </p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/fs/inode.rs</span>
<span class="k">impl</span><span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">OSInode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">readable</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">bool</span> <span class="p">{</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">readable</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">writable</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">bool</span> <span class="p">{</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">writable</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">read</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span>: <span class="nc">UserBuffer</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">inner</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">inner</span><span class="p">.</span><span class="n">lock</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">total_read_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="k">usize</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">slice</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">buffers</span><span class="p">.</span><span class="n">iter_mut</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">read_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inner</span><span class="p">.</span><span class="n">inode</span><span class="p">.</span><span class="n">read_at</span><span class="p">(</span><span class="n">inner</span><span class="p">.</span><span class="n">offset</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">slice</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">read_size</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">inner</span><span class="p">.</span><span class="n">offset</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">read_size</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="n">total_read_size</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">read_size</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">total_read_size</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">write</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span>: <span class="nc">UserBuffer</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">inner</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">inner</span><span class="p">.</span><span class="n">lock</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">total_write_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="k">usize</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">slice</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">buffers</span><span class="p">.</span><span class="n">iter</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">write_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inner</span><span class="p">.</span><span class="n">inode</span><span class="p">.</span><span class="n">write_at</span><span class="p">(</span><span class="n">inner</span><span class="p">.</span><span class="n">offset</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">slice</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">write_size</span><span class="p">,</span><span class="w"> </span><span class="n">slice</span><span class="p">.</span><span class="n">len</span><span class="p">());</span><span class="w"></span>
<span class="w"> </span><span class="n">inner</span><span class="p">.</span><span class="n">offset</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">write_size</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="n">total_write_size</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">write_size</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">total_write_size</span><span class="w"></span>
<span class="w"> </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">read/write</span></code> 的实现也比较简单,只需遍历 <code class="docutils literal notranslate"><span class="pre">UserBuffer</span></code> 中的每个缓冲区片段,调用 <code class="docutils literal notranslate"><span class="pre">Inode</span></code> 写好的 <code class="docutils literal notranslate"><span class="pre">read/write_at</span></code> 接口就好了。注意 <code class="docutils literal notranslate"><span class="pre">read/write_at</span></code> 的起始位置是在 <code class="docutils literal notranslate"><span class="pre">OSInode</span></code> 中维护的 <code class="docutils literal notranslate"><span class="pre">offset</span></code> ,这个 <code class="docutils literal notranslate"><span class="pre">offset</span></code> 也随着遍历的进行被持续更新。在 <code class="docutils literal notranslate"><span class="pre">read/write</span></code> 的全程需要获取 <code class="docutils literal notranslate"><span class="pre">OSInode</span></code> 的互斥锁,保证两个进程无法同时访问同个文件。</p>
<p>本章我们为 <code class="docutils literal notranslate"><span class="pre">File</span></code> Trait 新增了 <code class="docutils literal notranslate"><span class="pre">readable/writable</span></code> 两个抽象接口,从而在 <code class="docutils literal notranslate"><span class="pre">sys_read/sys_write</span></code> 的时候进行简单的访问权限检查。</p>
</div>
<div class="section" id="id4">
<h2>文件系统相关内核机制实现<a class="headerlink" href="#id4" title="永久链接至标题"></a></h2>
<div class="section" id="id5">
<h3>文件系统初始化<a class="headerlink" href="#id5" title="永久链接至标题"></a></h3>
<p>为了使用 <code class="docutils literal notranslate"><span class="pre">easy-fs</span></code> 提供的抽象,内核需要进行一些初始化操作。我们需要从块设备 <code class="docutils literal notranslate"><span class="pre">BLOCK_DEVICE</span></code> 上打开文件系统,并从文件系统中获取根目录的 inode 。</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/fs/inode.rs</span>
<span class="n">lazy_static</span><span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">ref</span><span class="w"> </span><span class="n">ROOT_INODE</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">Inode</span><span class="o">&gt;</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="kd">let</span><span class="w"> </span><span class="n">efs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">EasyFileSystem</span>::<span class="n">open</span><span class="p">(</span><span class="n">BLOCK_DEVICE</span><span class="p">.</span><span class="n">clone</span><span class="p">());</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">EasyFileSystem</span>::<span class="n">root_inode</span><span class="p">(</span><span class="o">&amp;</span><span class="n">efs</span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
<p>这之后就可以使用根目录的 inode <code class="docutils literal notranslate"><span class="pre">ROOT_INODE</span></code> ,在内核中调用 <code class="docutils literal notranslate"><span class="pre">easy-fs</span></code> 的相关接口了。例如,在文件系统初始化完毕之后,调用 <code class="docutils literal notranslate"><span class="pre">list_apps</span></code> 函数来打印所有可用应用的文件名:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/fs/inode.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">list_apps</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"/**** APPS ****"</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">app</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">ROOT_INODE</span><span class="p">.</span><span class="n">ls</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">app</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"**************/"</span><span class="p">)</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
</div>
<div class="section" id="sys-open">
<h3>通过 sys_open 打开文件<a class="headerlink" href="#sys-open" title="永久链接至标题"></a></h3>
<p>在内核中也定义一份打开文件的标志 <code class="docutils literal notranslate"><span class="pre">OpenFlags</span></code> </p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/fs/inode.rs</span>
<span class="n">bitflags</span><span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">OpenFlags</span>: <span class="kt">u32</span> <span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">RDONLY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">WRONLY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">RDWR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">CREATE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="mi">9</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">TRUNC</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="k">impl</span><span class="w"> </span><span class="n">OpenFlags</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="sd">/// Do not check validity for simplicity</span>
<span class="w"> </span><span class="sd">/// Return (readable, writable)</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">read_write</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="p">(</span><span class="kt">bool</span><span class="p">,</span><span class="w"> </span><span class="kt">bool</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">is_empty</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="bp">Self</span>::<span class="n">WRONLY</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="kc">true</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </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">read_write</span></code> 方法可以根据标志的情况返回要打开的文件是否允许读写。简单起见,这里假设标志自身一定合法。</p>
<p>接着,我们实现 <code class="docutils literal notranslate"><span class="pre">open_file</span></code> 内核函数,可根据文件名打开一个根目录下的文件:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/fs/inode.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">open_file</span><span class="p">(</span><span class="n">name</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">,</span><span class="w"> </span><span class="n">flags</span>: <span class="nc">OpenFlags</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="n">Arc</span><span class="o">&lt;</span><span class="n">OSInode</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">readable</span><span class="p">,</span><span class="w"> </span><span class="n">writable</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">flags</span><span class="p">.</span><span class="n">read_write</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">flags</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">OpenFlags</span>::<span class="n">CREATE</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">inode</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ROOT_INODE</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">name</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="c1">// clear size</span>
<span class="w"> </span><span class="n">inode</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">OSInode</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">readable</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">writable</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inode</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">)))</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="c1">// create file</span>
<span class="w"> </span><span class="n">ROOT_INODE</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="n">name</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">OSInode</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">readable</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">writable</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inode</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">ROOT_INODE</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">name</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="o">|</span><span class="n">inode</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">flags</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">OpenFlags</span>::<span class="n">TRUNC</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="n">inode</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">(</span><span class="n">OSInode</span>::<span class="n">new</span><span class="p">(</span><span class="w"></span>
<span class="w"> </span><span class="n">readable</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">writable</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="n">inode</span><span class="w"></span>
<span class="w"> </span><span class="p">))</span><span class="w"></span>
<span class="w"> </span><span class="p">})</span><span class="w"></span>
<span class="w"> </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">OpenFlags</span></code> 各标志位的语义。例如只有 <code class="docutils literal notranslate"><span class="pre">flags</span></code> 参数包含 <cite>CREATE</cite> 标志位才允许创建文件;而如果文件已经存在,则清空文件的内容。</p>
<p>在其基础上, <code class="docutils literal notranslate"><span class="pre">sys_open</span></code> 也就很容易实现了。</p>
</div>
<div class="section" id="sys-exec">
<h3>通过 sys_exec 加载并执行应用<a class="headerlink" href="#sys-exec" title="永久链接至标题"></a></h3>
<p>有了文件系统支持后, <code class="docutils literal notranslate"><span class="pre">sys_exec</span></code> 所需的表示应用 ELF 格式数据改为从文件系统中获取:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="c1">// os/src/syscall/process.rs</span>
<span class="linenos"> 2</span>
<span class="linenos"> 3</span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">sys_exec</span><span class="p">(</span><span class="n">path</span>: <span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">args</span>: <span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">isize</span> <span class="p">{</span><span class="w"></span>
<span class="linenos"> 4</span><span class="kd">let</span><span class="w"> </span><span class="n">token</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">current_user_token</span><span class="p">();</span><span class="w"></span>
<span class="linenos"> 5</span><span class="kd">let</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">translated_str</span><span class="p">(</span><span class="n">token</span><span class="p">,</span><span class="w"> </span><span class="n">path</span><span class="p">);</span><span class="w"></span>
<span class="linenos"> 6</span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">args_vec</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="nb">String</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="linenos"> 7</span><span class="k">loop</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos"> 8</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">arg_str_ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="n">translated_ref</span><span class="p">(</span><span class="n">token</span><span class="p">,</span><span class="w"> </span><span class="n">args</span><span class="p">);</span><span class="w"></span>
<span class="linenos"> 9</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">arg_str_ptr</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">10</span><span class="w"> </span><span class="k">break</span><span class="p">;</span><span class="w"></span>
<span class="linenos">11</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">12</span><span class="w"> </span><span class="n">args_vec</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">translated_str</span><span class="p">(</span><span class="n">token</span><span class="p">,</span><span class="w"> </span><span class="n">arg_str_ptr</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="kt">u8</span><span class="p">));</span><span class="w"></span>
<span class="linenos">13</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="linenos">14</span><span class="w"> </span><span class="n">args</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">args</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span><span class="w"></span>
<span class="linenos">15</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="linenos">16</span><span class="p">}</span><span class="w"></span>
<span class="hll"><span class="linenos">17</span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">app_inode</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">open_file</span><span class="p">(</span><span class="n">path</span><span class="p">.</span><span class="n">as_str</span><span class="p">(),</span><span class="w"> </span><span class="n">OpenFlags</span>::<span class="n">RDONLY</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class="hll"><span class="linenos">18</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">all_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">app_inode</span><span class="p">.</span><span class="n">read_all</span><span class="p">();</span><span class="w"></span>
</span><span class="hll"><span class="linenos">19</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">current_task</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
</span><span class="hll"><span class="linenos">20</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">argc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">args_vec</span><span class="p">.</span><span class="n">len</span><span class="p">();</span><span class="w"></span>
</span><span class="hll"><span class="linenos">21</span><span class="w"> </span><span class="n">task</span><span class="p">.</span><span class="n">exec</span><span class="p">(</span><span class="n">all_data</span><span class="p">.</span><span class="n">as_slice</span><span class="p">(),</span><span class="w"> </span><span class="n">args_vec</span><span class="p">);</span><span class="w"></span>
</span><span class="hll"><span class="linenos">22</span><span class="w"> </span><span class="n">argc</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">isize</span><span class="w"></span>
</span><span class="hll"><span class="linenos">23</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
</span><span class="hll"><span class="linenos">24</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w"></span>
</span><span class="hll"><span class="linenos">25</span><span class="p">}</span><span class="w"></span>
</span></pre></div>
</div>
<p>注意上面代码片段中的高亮部分。当执行获取应用的 ELF 数据的操作时,首先调用 <code class="docutils literal notranslate"><span class="pre">open_file</span></code> 函数,以只读的方式在内核中打开应用文件并获取它对应的 <code class="docutils literal notranslate"><span class="pre">OSInode</span></code> 。接下来可以通过 <code class="docutils literal notranslate"><span class="pre">OSInode::read_all</span></code> 将该文件的数据全部读到一个向量 <code class="docutils literal notranslate"><span class="pre">all_data</span></code> 中:</p>
<p>之后,就可以从向量 <code class="docutils literal notranslate"><span class="pre">all_data</span></code> 中拿到应用中的 ELF 数据,当解析完毕并创建完应用地址空间后该向量将会被回收。</p>
<p>同样的,我们在内核中创建初始进程 <code class="docutils literal notranslate"><span class="pre">initproc</span></code> 也需要替换为基于文件系统的实现:</p>
<div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="c1">// os/src/task/mod.rs</span>
<span class="n">lazy_static</span><span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">ref</span><span class="w"> </span><span class="n">INITPROC</span>: <span class="nc">Arc</span><span class="o">&lt;</span><span class="n">TaskControlBlock</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arc</span>::<span class="n">new</span><span class="p">({</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">inode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">open_file</span><span class="p">(</span><span class="s">"ch6b_initproc"</span><span class="p">,</span><span class="w"> </span><span class="n">OpenFlags</span>::<span class="n">RDONLY</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inode</span><span class="p">.</span><span class="n">read_all</span><span class="p">();</span><span class="w"></span>
<span class="w"> </span><span class="n">TaskControlBlock</span>::<span class="n">new</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">as_slice</span><span class="p">())</span><span class="w"></span>
<span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>
</div>
</div>
</div>
</div>
</article>
<footer>
<div class="related-pages">
<a class="next-page" href="4exercise.html">
<div class="page-info">
<div class="context">
<span>Next</span>
</div>
<div class="title">chapter6练习</div>
</div>
<svg><use href="#svg-arrow-right"></use></svg>
</a>
<a class="prev-page" href="2fs-implementation-2.html">
<svg><use href="#svg-arrow-right"></use></svg>
<div class="page-info">
<div class="context">
<span>Previous</span>
</div>
<div class="title">简易文件系统 easy-fs (下)</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/chapter6/3using-easy-fs-in-kernel.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="#">在内核中使用 easy-fs</a><ul>
<li><a class="reference internal" href="#id1">块设备驱动层</a></li>
<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><ul>
<li><a class="reference internal" href="#id5">文件系统初始化</a></li>
<li><a class="reference internal" href="#sys-open">通过 sys_open 打开文件</a></li>
<li><a class="reference internal" href="#sys-exec">通过 sys_exec 加载并执行应用</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</aside>
</div>
</div><script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/scripts/main.js"></script>
<script kind="utterances">
var commentsRunWhenDOMLoaded = cb => {
if (document.readyState != 'loading') {
cb()
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', cb)
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState == 'complete') cb()
})
}
}
var addUtterances = () => {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://utteranc.es/client.js";
script.async = "async";
script.setAttribute("repo", "LearningOS/rust-based-os-comp2022");
script.setAttribute("issue-term", "pathname");
script.setAttribute("theme", "github-light");
script.setAttribute("label", "comments");
script.setAttribute("crossorigin", "anonymous");
sections = document.querySelectorAll("div.section");
if (sections !== null) {
section = sections[sections.length-1];
section.appendChild(script);
}
}
commentsRunWhenDOMLoaded(addUtterances);
</script>
<script src="../_static/translations.js"></script>
</body>
</html>