mirror of
https://github.com/LearningOS/rust-based-os-comp2022.git
synced 2026-02-08 12:53:34 +08:00
682 lines
74 KiB
HTML
682 lines
74 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="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">附录 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="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"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">BlockDevice</span><span class="o">></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">&</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">&</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>-> <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"><</span><span class="n">OSInodeInner</span><span class="o">></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"><</span><span class="n">Inode</span><span class="o">></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">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <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">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <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">&</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>-> <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">&</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>-> <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"><</span><span class="n">Inode</span><span class="o">></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">&</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"><<</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"><<</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"><<</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"><<</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">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <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">&</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>-> <span class="nb">Option</span><span class="o"><</span><span class="n">Arc</span><span class="o"><</span><span class="n">OSInode</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="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>-> <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"><</span><span class="nb">String</span><span class="o">></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"><</span><span class="n">TaskControlBlock</span><span class="o">></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 © 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> |