-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlab6.html
More file actions
185 lines (184 loc) · 65.2 KB
/
Copy pathlab6.html
File metadata and controls
185 lines (184 loc) · 65.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="VuePress 2.0.0-rc.14">
<script>
(function() {
const userMode = localStorage.getItem('vuepress-reco-color-scheme') || 'auto';
const systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
if (userMode === 'dark' || (userMode === 'auto' && systemDarkMode)) {
document.documentElement.classList.toggle('dark', true);
}
})();
</script>
<title>Lab6实验报告 | Yunge Hu 's Blog</title><meta name="description" content="Just playing around">
<link rel="preload" href="/assets/style-DFiSfBVn.css" as="style"><link rel="stylesheet" href="/assets/style-DFiSfBVn.css">
<link rel="modulepreload" href="/assets/app-B51tXhJU.js"><link rel="modulepreload" href="/assets/lab6.html-ueb45YH9.js">
<link rel="prefetch" href="/assets/timeline.html-CDRCyYXN.js" as="script"><link rel="prefetch" href="/assets/posts.html-Cm3Bj9S1.js" as="script"><link rel="prefetch" href="/assets/friendship-link.html-CPYWbDf2.js" as="script"><link rel="prefetch" href="/assets/1.html-BvGA5exa.js" as="script"><link rel="prefetch" href="/assets/1.html-CQiPtbSY.js" as="script"><link rel="prefetch" href="/assets/1.html-B91OJGi4.js" as="script"><link rel="prefetch" href="/assets/1.html-Tfqc0eqa.js" as="script"><link rel="prefetch" href="/assets/1.html-DkR1aWCw.js" as="script"><link rel="prefetch" href="/assets/1.html-9JnLqyKk.js" as="script"><link rel="prefetch" href="/assets/2.html-Bgp2cdo4.js" as="script"><link rel="prefetch" href="/assets/3.html-BrEt4hPg.js" as="script"><link rel="prefetch" href="/assets/index.html-BKyJy_kV.js" as="script"><link rel="prefetch" href="/assets/Install-Neo4j-in-Ubuntu-and-Use-Gremlin.html-D3zJqoKu.js" as="script"><link rel="prefetch" href="/assets/Neo4j.html-RU17f5ie.js" as="script"><link rel="prefetch" href="/assets/index.html-DTD_Tf27.js" as="script"><link rel="prefetch" href="/assets/README.zh.html-C95KaJWV.js" as="script"><link rel="prefetch" href="/assets/Javajibenchengxushejijiegou.html-Cop84p5k.js" as="script"><link rel="prefetch" href="/assets/Javamianxiangduixiangchengxusheji——duixiangyulei.html-RHrWrJ8D.js" as="script"><link rel="prefetch" href="/assets/Javamianxiangduixiangchengxusheji——jiekou、lambdabiaodashiyunabulei.html-B4BIhUeh.js" as="script"><link rel="prefetch" href="/assets/Javamianxiangduixiangchengxusheji——jicheng.html-CDNHmPwq.js" as="script"><link rel="prefetch" href="/assets/bingfa.html-BObwH6f-.js" as="script"><link rel="prefetch" href="/assets/yichangduanyanherizhi.html-Bw2Q646T.js" as="script"><link rel="prefetch" href="/assets/fanxingyujihe.html-ChyCepcN.js" as="script"><link rel="prefetch" href="/assets/index.html-B_tI2L4g.js" as="script"><link rel="prefetch" href="/assets/suoyincaozuo.html-M9SgPFiv.js" as="script"><link rel="prefetch" href="/assets/lab0.html-DQt1B-xd.js" as="script"><link rel="prefetch" href="/assets/lab1.html-Dvm30kLN.js" as="script"><link rel="prefetch" href="/assets/lab2.html-gAWXyUFt.js" as="script"><link rel="prefetch" href="/assets/lab3.html-LQVGolsr.js" as="script"><link rel="prefetch" href="/assets/lab4.html-CF_2B461.js" as="script"><link rel="prefetch" href="/assets/lab5.html-2WxLf5I9.js" as="script"><link rel="prefetch" href="/assets/index.html-CjBzVZj0.js" as="script"><link rel="prefetch" href="/assets/404.html-Dk0UZDtj.js" as="script"><link rel="prefetch" href="/assets/Valine.min-Dm4Ijz6H.js" as="script"><link rel="prefetch" href="/assets/giscus-2a044aea-CdPDkb7_.js" as="script">
</head>
<body>
<div id="app"><!--[--><div class="theme-container series--no show-catalog"><header class="navbar-container not-open"><div class="navbar-inner"><div class="site-brand nav-item"><img class="logo" src="/logo.png" alt="Yunge Hu 's Blog"><a href="/" class="site-name can-hide">Yunge Hu 's Blog</a></div><div class="nav-item navbar-links-wrapper" style=""><div><form class="search-box" role="search"><input type="search" autocomplete="off" spellcheck="false" value><!----></form></div><nav class="navbar-links"><!--[--><div class="navbar-links__item"><a href="/" class="link router-link-active" aria-label="Home"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Home<!--]--></span></span><!--[--><!--]--></a></div><div class="navbar-links__item"><a class="link" href="https://github.com/gitDebuger/gitdebuger.github.io" target="_blank" rel="noopener noreferrer" aria-label="GitHub"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->GitHub<!--]--></span></span><span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!--[--><!--]--></a></div><!--]--></nav><span class="xicon-container btn-toggle-dark-mode btn--dark-mode"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M15 2h2v3h-2z" fill="currentColor"></path><path d="M27 15h3v2h-3z" fill="currentColor"></path><path d="M15 27h2v3h-2z" fill="currentColor"></path><path d="M2 15h3v2H2z" fill="currentColor"></path><path d="M5.45 6.884l1.414-1.415l2.121 2.122l-1.414 1.414z" fill="currentColor"></path><path d="M23 7.58l2.121-2.12l1.414 1.414l-2.121 2.121z" fill="currentColor"></path><path d="M23.002 24.416l1.415-1.414l2.12 2.122l-1.413 1.414z" fill="currentColor"></path><path d="M5.47 25.13L7.59 23L9 24.42l-2.12 2.12l-1.41-1.41z" fill="currentColor"></path><path d="M16 8a8 8 0 1 0 8 8a8 8 0 0 0-8-8zm0 14a6 6 0 0 1 0-12z" fill="currentColor"></path></svg></span><span class="xicon-container btn-toggle-menus"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><circle cx="16" cy="8" r="2" fill="currentColor"></circle><circle cx="16" cy="16" r="2" fill="currentColor"></circle><circle cx="16" cy="24" r="2" fill="currentColor"></circle></svg></span></div></div></header><!----><!----><!----><!--[--><main class="page-container"><aside class="series-container"><!--[--><!--]--></aside><div class="page-content"><h1 class="page-title">Lab6实验报告</h1><div class="page-info"><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M16 4a5 5 0 1 1-5 5a5 5 0 0 1 5-5m0-2a7 7 0 1 0 7 7a7 7 0 0 0-7-7z" fill="currentColor"></path><path d="M26 30h-2v-5a5 5 0 0 0-5-5h-6a5 5 0 0 0-5 5v5H6v-5a7 7 0 0 1 7-7h6a7 7 0 0 1 7 7z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Yunge Hu<!--]--></span></span><!----><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M11.17 6l3.42 3.41l.58.59H28v16H4V6h7.17m0-2H4a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2H16l-3.41-3.41A2 2 0 0 0 11.17 4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[--><!--[--><a href="/categories/OS/1.html" class="">OS</a><!--]--><!--]--></span></span><!----><!----></div><div class="theme-reco-md-content"><div><h1 id="lab6实验报告" tabindex="-1"><a class="header-anchor" href="#lab6实验报告"><span>Lab6实验报告</span></a></h1><h2 id="_1-思考题" tabindex="-1"><a class="header-anchor" href="#_1-思考题"><span>1. 思考题</span></a></h2><h3 id="_1-1-thinking-6-1" tabindex="-1"><a class="header-anchor" href="#_1-1-thinking-6-1"><span>1.1 Thinking 6.1</span></a></h3><p><strong>示例代码中,父进程操作管道的写端,子进程操作管道的读端。如果现在想让父进程作为“读者”,代码应当如何修改?</strong></p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><stdlib.h></span></span></span>
<span class="line"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><unistd.h></span></span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">int</span> fildes<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token comment">/* buf size is 100 */</span></span>
<span class="line"><span class="token keyword">char</span> buf<span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">int</span> status<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> status <span class="token operator">=</span> <span class="token function">pipe</span><span class="token punctuation">(</span>fildes<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span>status <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token comment">/* an error occurred */</span></span>
<span class="line"> <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"error\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token keyword">switch</span> <span class="token punctuation">(</span><span class="token function">fork</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">case</span> <span class="token operator">-</span><span class="token number">1</span><span class="token operator">:</span> <span class="token comment">/* Handle error */</span></span>
<span class="line"> <span class="token keyword">break</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">case</span> <span class="token number">0</span><span class="token operator">:</span> <span class="token comment">/* Child - writes to pipe */</span></span>
<span class="line"> <span class="token function">close</span><span class="token punctuation">(</span>fildes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Read end is unused */</span></span>
<span class="line"> <span class="token function">write</span><span class="token punctuation">(</span>fildes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">"Hello world\n"</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Write data on pipe */</span></span>
<span class="line"> <span class="token function">close</span><span class="token punctuation">(</span>fildes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Child will see EOF */</span></span>
<span class="line"> <span class="token function">exit</span><span class="token punctuation">(</span>EXIT_SUCCESS<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token comment">/* Parent - reads from pipe */</span></span>
<span class="line"> <span class="token function">close</span><span class="token punctuation">(</span>fildes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Write end is unused */</span></span>
<span class="line"> <span class="token function">read</span><span class="token punctuation">(</span>fildes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> buf<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Get data from pipe */</span></span>
<span class="line"> <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"parent-process read:%s"</span><span class="token punctuation">,</span> buf<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Print the data */</span></span>
<span class="line"> <span class="token function">close</span><span class="token punctuation">(</span>fildes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Finished with pipe */</span></span>
<span class="line"> <span class="token function">exit</span><span class="token punctuation">(</span>EXIT_SUCCESS<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>也就是交换 <code>case 0</code> 和 <code>case 1</code> 处的代码。</p><h3 id="_1-2-thinking-6-2" tabindex="-1"><a class="header-anchor" href="#_1-2-thinking-6-2"><span>1.2 Thinking 6.2</span></a></h3><p><strong>上面这种不同步修改 <code>pp_ref</code> 而导致的进程竞争问题在 <code>user/lib/fd.c</code> 中的 <code>dup</code> 函数中也存在。请结合代码模仿上述情景,分析一下我们的 <code>dup</code> 函数中为什么会出现预想之外的情况?</strong></p><p><code>dup</code> 函数的功能是将文件描述符 <code>oldfdnum</code> 所对应的内容映射到文件描述符 <code>newfdnum</code> 中,会将 <code>oldfdnum</code> 和 <code>pipe</code> 的引用次数都增加 <code>1</code> ,将 <code>newfdnum</code> 的引用次数变为 <code>oldfdnum</code> 的引用次数。</p><p>当我们将一个管道的读/写端对应的文件描述符映射到另一个文件描述符。在进行映射之前,<code>f[0]</code> <code>f[1]</code> <code>pipe</code> 的引用次数分别为 <code>1</code> <code>1</code> <code>2</code> 。按照 <code>dup</code> 函数的执行顺序,会先将 <code>fd[0]</code> 引用次数 <code>+1</code> ,再将 <code>pipe</code> 引用次数 <code>+1</code> ,如果 <code>fd[0]</code> 的引用次数 <code>+1</code> 后恰好发生了一次时钟中断,进程切换后,另一进程调用 <code>_pipeisclosed</code> 函数判断管道写端是否关闭,此时 <code>pageref(fd[0]) == pageref(pipe) == 2</code> ,所以会误认为写端关闭,从而出现判断错误。</p><h3 id="_1-3-thinking-6-3" tabindex="-1"><a class="header-anchor" href="#_1-3-thinking-6-3"><span>1.3 Thinking 6.3</span></a></h3><p><strong>阅读上述材料并思考:为什么系统调用一定是原子操作呢?如果你觉得不是所有的系统调用都是原子操作,请给出反例。希望能结合相关代码进行分析说明。</strong></p><p>不只是系统调用,所有的异常处理函数都是原子操作。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token comment">/* 定义通用异常入口点 */</span></span>
<span class="line"><span class="token punctuation">.</span>section <span class="token punctuation">.</span>text<span class="token punctuation">.</span>exc_gen_entry</span>
<span class="line">exc_gen_entry<span class="token operator">:</span></span>
<span class="line"> <span class="token comment">/* 首先保存了所有寄存器的状态 */</span></span>
<span class="line"> SAVE_ALL</span>
<span class="line"> <span class="token comment">/* 重置了处理器的状态 */</span></span>
<span class="line"> <span class="token comment">/* 确保处理器处于内核模式并禁用了中断 */</span></span>
<span class="line"> <span class="token comment">/* 清除了状态寄存器中的用户模式 UM 位 */</span></span>
<span class="line"> <span class="token comment">/* 异常级别 EXL 位和全局中断使能 IE 位 */</span></span>
<span class="line"> mfc0 t0<span class="token punctuation">,</span> CP0_STATUS</span>
<span class="line"> and t0<span class="token punctuation">,</span> t0<span class="token punctuation">,</span> <span class="token operator">~</span><span class="token punctuation">(</span>STATUS_UM <span class="token operator">|</span> STATUS_EXL <span class="token operator">|</span> STATUS_IE<span class="token punctuation">)</span></span>
<span class="line"> mtc0 t0<span class="token punctuation">,</span> CP0_STATUS</span>
<span class="line"> <span class="token comment">/* 获取异常原因并跳转到相应的异常处理函数 */</span></span>
<span class="line"> mfc0 t0<span class="token punctuation">,</span> CP0_CAUSE</span>
<span class="line"> andi t0<span class="token punctuation">,</span> <span class="token number">0x7c</span></span>
<span class="line"> lw t0<span class="token punctuation">,</span> <span class="token function">exception_handlers</span><span class="token punctuation">(</span>t0<span class="token punctuation">)</span></span>
<span class="line"> jr t0</span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这是 <code>kern/entry.S</code> 中定义的通用异常入口点,在这里会禁用中断,从而避免再次触发异常处理,从而确保当前异常处理函数为原子操作。从而,所有的系统调用都是原子操作。</p><h3 id="_1-4-thinking-6-4" tabindex="-1"><a class="header-anchor" href="#_1-4-thinking-6-4"><span>1.4 Thinking 6.4</span></a></h3><p><strong>仔细阅读上面这段话,并思考下列问题:</strong></p><ul><li><strong>按照上述说法控制 <code>pipe_close</code> 中 <code>fd</code> 和 <code>pipe_unmap</code> 的顺序,是否可以解决上述场景的进程竞争问题?给出你的分析过程。</strong></li><li><strong>我们只分析了 <code>close</code> 时的情形,在 <code>fd.c</code> 中有一个 <code>dup</code> 函数,用于复制文件描述符。试想,如果要复制的文件描述符指向一个管道,那么是否会出现与 <code>close</code> 类似的问题?请模仿上述材料写写你的理解。</strong></li></ul><p>回答如下:</p><ul><li>可以解决。如果程序正常运行,那么 <code>pipe</code> 的 <code>pageref</code> 是要大于 <code>fd</code> 的,在执行 <code>unmap</code> 操作时,优先解除 <code>fd</code> 的映射,这样就可保证严格大于关系恒成立,即使发生了时钟中断,也不会出现运行错误。</li><li>同样的道理,在 <code>dup</code> 使引用次数增加时,先将 <code>pipe</code> 的引用次数增加,保证不会出现两者相等的情况。</li></ul><h3 id="_1-5-thinking-6-5" tabindex="-1"><a class="header-anchor" href="#_1-5-thinking-6-5"><span>1.5 Thinking 6.5</span></a></h3><p><strong>思考以下三个问题。</strong></p><ul><li><strong>认真回看Lab5文件系统相关代码,弄清打开文件的过程。</strong></li><li><strong>回顾Lab1与 Lab3,思考如何读取并加载 <code>ELF</code> 文件。</strong></li><li><strong>在Lab1中我们介绍了 <code>data</code> <code>text</code> <code>bss</code> 段及它们的含义,<code>data</code> 段存放初始化过的全局变量,<code>bss</code> 段存放未初始化的全局变量。关于 <code>memsize</code> 和 <code>filesize</code> ,我们在Note 1.3.4中也解释了它们的含义与特点。关于Note 1.3.4,注意其中关于“ <code>bss</code> 段并不在文件中占数据”表述的含义。回顾Lab3并思考:<code>elf_load_seg()</code> 和 <code>load_icode_mapper()</code> 函数是如何确保加载 <code>ELF</code> 文件时,<code>bss</code> 段数据被正确加载进虚拟内存空间。<code>bss</code> 段在 <code>ELF</code> 中并不占空间,但 <code>ELF</code> 加载进内存后,<code>bss</code> 段的数据占据了空间,并且初始值都是 <code>0</code> 。请回顾 <code>elf_load_seg()</code> 和 <code>load_icode_mapper()</code> 的实现,思考这一点是如何实现的?</strong></li></ul><p>回答如下:</p><ul><li><p>用户进程通过 <code>user/lib/file.c</code> 中的 <code>open</code> 函数完成打开文件操作。在该函数中,首先调用 <code>fd_alloc</code> 申请一个文件描述符,但是这里只是得到了可以作为文件描述符的地址,还没有实际的文件描述符数据。之后调用 <code>fsipc_open</code> ,该函数会将 <code>path</code> 对应的文件以 <code>mode</code> 的方式打开,将该文件的文件描述符共享到 <code>fd</code> 指针对应的地址处。</p><p>虽然获得了服务进程共享给用户进程的文件描述符,可文件的内容还没有被一同共享过来,接下来还需要使用 <code>fsipc_map</code> 进行映射。先做准备工作,通过 <code>fd2data</code> 获取文件内容应该映射到的地址;接着将文件所有的内容都从磁盘中映射到内存。</p><p>在最后,使用 <code>fd2num</code> 方法获取文件描述符在文件描述符数组中的索引,并将其返回给调用者。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">int</span> <span class="token function">open</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">char</span> <span class="token operator">*</span>path<span class="token punctuation">,</span> <span class="token keyword">int</span> mode<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">int</span> r<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Fd</span> <span class="token operator">*</span>fd<span class="token punctuation">;</span></span>
<span class="line"> <span class="token comment">// 申请文件描述符</span></span>
<span class="line"> <span class="token function">try</span><span class="token punctuation">(</span><span class="token function">fd_alloc</span><span class="token punctuation">(</span><span class="token operator">&</span>fd<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token comment">// 打开文件并将文件描述符共享到 fd 指针对应地址处</span></span>
<span class="line"> <span class="token function">try</span><span class="token punctuation">(</span><span class="token function">fsipc_open</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> mode<span class="token punctuation">,</span> fd<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token comment">// 映射文件内容</span></span>
<span class="line"> <span class="token keyword">char</span> <span class="token operator">*</span>va<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Filefd</span> <span class="token operator">*</span>ffd<span class="token punctuation">;</span></span>
<span class="line"> u_int size<span class="token punctuation">,</span> fileid<span class="token punctuation">;</span></span>
<span class="line"> va <span class="token operator">=</span> <span class="token function">fd2data</span><span class="token punctuation">(</span>fd<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> ffd <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> <span class="token class-name">Filefd</span> <span class="token operator">*</span><span class="token punctuation">)</span>fd<span class="token punctuation">;</span></span>
<span class="line"> size <span class="token operator">=</span> ffd<span class="token operator">-></span>f_file<span class="token punctuation">.</span>f_size<span class="token punctuation">;</span></span>
<span class="line"> fileid <span class="token operator">=</span> ffd<span class="token operator">-></span>f_fileid<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> size<span class="token punctuation">;</span> i <span class="token operator">+=</span> PTMAP<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token function">try</span><span class="token punctuation">(</span><span class="token function">fsipc_map</span><span class="token punctuation">(</span>fileid<span class="token punctuation">,</span> i<span class="token punctuation">,</span> va <span class="token operator">+</span> i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token comment">// 返回索引</span></span>
<span class="line"> <span class="token keyword">return</span> <span class="token function">fd2num</span><span class="token punctuation">(</span>fd<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>除此之外,还可以在 <code>mips_init</code> 函数中在操作系统初始化时创建初始进程,此时直接从宿主机中读取文件。</p></li><li><p>加载 <code>ELF</code> 文件主要是通过 <code>lib/elfloader.c</code> 中的 <code>elf_load_seg</code> 函数。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">int</span> <span class="token function">elf_load_seg</span><span class="token punctuation">(</span>Elf32_Phdr <span class="token operator">*</span>ph<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">void</span> <span class="token operator">*</span>bin<span class="token punctuation">,</span> <span class="token class-name">elf_mapper_t</span> map_page<span class="token punctuation">,</span> <span class="token keyword">void</span> <span class="token operator">*</span>data<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> u_long va <span class="token operator">=</span> ph<span class="token operator">-></span>p_vaddr<span class="token punctuation">;</span></span>
<span class="line"> <span class="token class-name">size_t</span> bin_size <span class="token operator">=</span> ph<span class="token operator">-></span>p_filesz<span class="token punctuation">;</span></span>
<span class="line"> <span class="token class-name">size_t</span> sgsize <span class="token operator">=</span> ph<span class="token operator">-></span>p_memsz<span class="token punctuation">;</span></span>
<span class="line"> u_int perm <span class="token operator">=</span> PTE_V<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span>ph<span class="token operator">-></span>p_flags <span class="token operator">&</span> PF_W<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> perm <span class="token operator">|=</span> PTE_D<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token comment">/* 首先需要处理要加载的虚拟地址不与页对齐的情况 */</span></span>
<span class="line"> <span class="token comment">/* 将最开头不对齐的部分剪切下来先映射到内存的页中 */</span></span>
<span class="line"> <span class="token keyword">int</span> r<span class="token punctuation">;</span></span>
<span class="line"> <span class="token class-name">size_t</span> i<span class="token punctuation">;</span></span>
<span class="line"> u_long offset <span class="token operator">=</span> va <span class="token operator">-</span> <span class="token function">ROUNDDOWN</span><span class="token punctuation">(</span>va<span class="token punctuation">,</span> PAGE_SIZE<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span>offset <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">=</span> <span class="token function">map_page</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> va<span class="token punctuation">,</span> offset<span class="token punctuation">,</span> perm<span class="token punctuation">,</span> bin<span class="token punctuation">,</span></span>
<span class="line"> <span class="token function">MIN</span><span class="token punctuation">(</span>bin_size<span class="token punctuation">,</span> PAGE_SIZE <span class="token operator">-</span> offset<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">return</span> r<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token comment">/* 接着处理数据后面的部分 */</span></span>
<span class="line"> <span class="token comment">/* 通过循环不断将数据加载到页上。 */</span></span>
<span class="line"> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> offset <span class="token operator">?</span> <span class="token function">MIN</span><span class="token punctuation">(</span>bin_size<span class="token punctuation">,</span> PAGE_SIZE <span class="token operator">-</span> offset<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> bin_size<span class="token punctuation">;</span> i <span class="token operator">+=</span> PAGE_SIZE<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">=</span> <span class="token function">map_page</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> va <span class="token operator">+</span> i<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> perm<span class="token punctuation">,</span> bin <span class="token operator">+</span> i<span class="token punctuation">,</span> <span class="token function">MIN</span><span class="token punctuation">(</span>bin_size <span class="token operator">-</span> i<span class="token punctuation">,</span> PAGE_SIZE<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span></span>
<span class="line"> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">return</span> r<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token comment">/* 最后我们处理段大小大于数据大小的情况 */</span></span>
<span class="line"> <span class="token comment">/* 在这一部分我们不断创建新的页 */</span></span>
<span class="line"> <span class="token comment">/* 但是并不向其中加载任何内容 */</span></span>
<span class="line"> <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> sgsize<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">=</span> <span class="token function">map_page</span><span class="token punctuation">(</span>data<span class="token punctuation">,</span> va <span class="token operator">+</span> i<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> perm<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">,</span> <span class="token function">MIN</span><span class="token punctuation">(</span>sgsize <span class="token operator">-</span> i<span class="token punctuation">,</span> PAGE_SIZE<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">return</span> r<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> i <span class="token operator">+=</span> PAGE_SIZE<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在调用该函数加载之前,还需要调用同文件中的 <code>elf_from</code> 函数检查要加载的文件是否为 <code>ELF</code> 文件。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">const</span> Elf32_Ehdr <span class="token operator">*</span><span class="token function">elf_from</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">void</span> <span class="token operator">*</span>binary<span class="token punctuation">,</span> <span class="token class-name">size_t</span> size<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">const</span> Elf32_Ehdr <span class="token operator">*</span>ehdr <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">const</span> Elf32_Ehdr <span class="token operator">*</span><span class="token punctuation">)</span>binary<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span>size <span class="token operator">>=</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>Elf32_Ehdr<span class="token punctuation">)</span> <span class="token operator">&&</span> ehdr<span class="token operator">-></span>e_ident<span class="token punctuation">[</span>EI_MAG0<span class="token punctuation">]</span> <span class="token operator">==</span> ELFMAG0 <span class="token operator">&&</span></span>
<span class="line"> ehdr<span class="token operator">-></span>e_ident<span class="token punctuation">[</span>EI_MAG1<span class="token punctuation">]</span> <span class="token operator">==</span> ELFMAG1 <span class="token operator">&&</span> ehdr<span class="token operator">-></span>e_ident<span class="token punctuation">[</span>EI_MAG2<span class="token punctuation">]</span> <span class="token operator">==</span> ELFMAG2 <span class="token operator">&&</span></span>
<span class="line"> ehdr<span class="token operator">-></span>e_ident<span class="token punctuation">[</span>EI_MAG3<span class="token punctuation">]</span> <span class="token operator">==</span> ELFMAG3 <span class="token operator">&&</span> ehdr<span class="token operator">-></span>e_type <span class="token operator">==</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">return</span> ehdr<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"> <span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这两个函数的调用者为 <code>kern/env.c</code> 中的 <code>load_icode</code> 函数。</p></li><li><p>处理 <code>bss</code> 段的函数是Lab3中的 <code>load_icode_mapper</code> 。在这个函数中,我们要对 <code>bss</code> 段进行内存分配,但不进行初始化。当 <code>bin_size < sgsize</code> 时,会将空位填 <code>0</code> ,在这段过程中为 <code>bss</code> 段的数据全部赋上了默认值 <code>0</code> 。</p></li></ul><h3 id="_1-6-thinking-6-6" tabindex="-1"><a class="header-anchor" href="#_1-6-thinking-6-6"><span>1.6 Thinking 6.6</span></a></h3><p><strong>通过阅读代码空白段的注释我们知道,将标准输入或输出定向到文件,需要我们将其 <code>dup</code> 到 <code>0</code> 或 <code>1</code> 号文件描述符。那么问题来了:在哪步 <code>0</code> 和 <code>1</code> 被安排为标准输入和标准输出?请分析代码执行流程,给出答案。</strong></p><p>在 <code>user/init.c</code> 中的 <code>main</code> 函数中有如下代码:</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token comment">// other codes ...</span></span>
<span class="line"><span class="token comment">// stdin should be 0, because no file descriptors are open yet</span></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">=</span> <span class="token function">opencons</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token function">user_panic</span><span class="token punctuation">(</span><span class="token string">"opencons: %d"</span><span class="token punctuation">,</span> r<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"><span class="token comment">// stdout</span></span>
<span class="line"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r <span class="token operator">=</span> <span class="token function">dup</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token function">user_panic</span><span class="token punctuation">(</span><span class="token string">"dup: %d"</span><span class="token punctuation">,</span> r<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"><span class="token comment">// other codes ...</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_1-7-thinking-6-7" tabindex="-1"><a class="header-anchor" href="#_1-7-thinking-6-7"><span>1.7 Thinking 6.7</span></a></h3><p><strong>在 <code>shell</code> 中执行的命令分为内置命令和外部命令。在执行内置命令时 <code>shell</code> 不需要 <code>fork</code> 一个子 <code>shell</code> ,如Linux系统中的 <code>cd</code> 命令。在执行外部命令时 <code>shell</code> 需要 <code>fork</code> 一个子 <code>shell</code> ,然后子 <code>shell</code> 去执行这条命令。</strong></p><p><strong>据此判断,在MOS中我们用到的 <code>shell</code> 命令是内置命令还是外部命令?请思考为什么Linux的 <code>cd</code> 命令是内部命令而不是外部命令?</strong></p><p>在MOS中,我们用到的 <code>shell</code> 命令是外部命令,需要 <code>fork</code> 一个子 <code>shell</code> 来执行命令。</p><p>Linux的 <code>cd</code> 指令是改变当前的工作目录,如果在子 <code>shell</code> 中执行,则改变的是子 <code>shell</code> 的工作目录,无法改变当前 <code>shell</code> 的工作目录。</p><h3 id="_1-8-thinking-6-8" tabindex="-1"><a class="header-anchor" href="#_1-8-thinking-6-8"><span>1.8 Thinking 6.8</span></a></h3><p><strong>在你的 <code>shell</code> 中输入命令 <code>ls.b | cat.b > motd</code> 。</strong></p><p><strong>请问你可以在你的 <code>shell</code> 中观察到几次 <code>spawn</code> ?分别对应哪个进程?</strong></p><p><strong>请问你可以在你的 <code>shell</code> 中观察到几次进程销毁?分别对应哪个进程?</strong></p><p>执行结果如下:</p><div class="language-yaml line-numbers-mode" data-highlighter="prismjs" data-ext="yml" data-title="yml"><pre class="language-yaml"><code><span class="line">$ ls.b <span class="token punctuation">|</span> cat.b <span class="token punctuation">></span> motd</span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00004003</span><span class="token punctuation">]</span> pipecreate</span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00005005</span><span class="token punctuation">]</span> destroying 00005005</span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00005005</span><span class="token punctuation">]</span> free env 00005005</span>
<span class="line">i am killed <span class="token punctuation">...</span></span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00005806</span><span class="token punctuation">]</span> destroying 00005806</span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00005806</span><span class="token punctuation">]</span> free env 00005806</span>
<span class="line">i am killed <span class="token punctuation">...</span></span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00004804</span><span class="token punctuation">]</span> destroying 00004804</span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00004804</span><span class="token punctuation">]</span> free env 00004804</span>
<span class="line">i am killed <span class="token punctuation">...</span></span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00004003</span><span class="token punctuation">]</span> destroying 00004003</span>
<span class="line"><span class="token punctuation">[</span><span class="token number">00004003</span><span class="token punctuation">]</span> free env 00004003</span>
<span class="line">i am killed <span class="token punctuation">...</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里没有观察到 <code>spwan</code> ,进程销毁次数为 <code>4</code> 。</p><h2 id="_2-难点分析" tabindex="-1"><a class="header-anchor" href="#_2-难点分析"><span>2. 难点分析</span></a></h2><p>这部分实验的核心在于 <code>user/lib/pipe.c</code> 中与管道相关的函数。</p><p>首先是 <code>_pipe_is_closed</code> 函数,其中需要使用一个循环,不断进行 <code>env_runs</code> 的判断,直到稳定为止。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">do</span> <span class="token punctuation">{</span></span>
<span class="line"> runs <span class="token operator">=</span> env<span class="token operator">-></span>env_runs<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"> fd_ref <span class="token operator">=</span> <span class="token function">pageref</span><span class="token punctuation">(</span>fd<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> pipe_ref <span class="token operator">=</span> <span class="token function">pageref</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token punctuation">}</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>runs <span class="token operator">!=</span> env<span class="token operator">-></span>env_runs<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后是 <code>pipe_read</code> 函数,在 <code>p_rpos >= p_wpos</code> 时不能立刻返回,而是应该根据 <code>_pipe_is_closed()</code> 的返回值判断管道是否关闭,若未关闭,应执行进程切换。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">while</span> <span class="token punctuation">(</span>p<span class="token operator">-></span>p_rpos <span class="token operator">>=</span> p<span class="token operator">-></span>p_wpos<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">||</span> <span class="token function">_pipe_is_closed</span><span class="token punctuation">(</span>fd<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">return</span> i<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token function">syscall_yield</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后是 <code>pipe_write</code> 函数,同理在 <code>p_wpos - p_rpos >= PIPE_SIZE</code> 时不能立刻返回,而是应该根据 <code>_pipe_is_closed()</code> 的返回值判断管道是否关闭,若未关闭,应执行进程切换。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">while</span> <span class="token punctuation">(</span>p<span class="token operator">-></span>p_wpos <span class="token operator">-</span> p<span class="token operator">-></span>p_rpos <span class="token operator">>=</span> PIPE_SIZE<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">_pipe_is_closed</span><span class="token punctuation">(</span>fd<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">return</span> i<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token function">syscall_yield</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="_3-实验体会" tabindex="-1"><a class="header-anchor" href="#_3-实验体会"><span>3. 实验体会</span></a></h2><p>这就是整个操作系统实验课的最后一部分了,~~我们成功体验到了从头搭建一个小操作系统的乐趣,~~至此,我们的操作系统虽然简单但是也还算完善,可以完成操作系统应该能够完成的大部分工作了。</p><p>在写下这篇实验报告时,操作系统理论课已经结束,实验课也就还有最后一次限时上机,期末考试也即将到来,我们真的要和操作系统课程说再见了。</p><p>回顾这一学期的操作系统课程,虽然内容很多,并且学得很累,但其实也还算有收获吧。不管怎么说吧,完结撒花!</p></div></div><footer class="page-meta"><div class="meta-item edit-link"><span class="xicon-container left meta-item-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M2 26h28v2H2z" fill="currentColor"></path><path d="M25.4 9c.8-.8.8-2 0-2.8l-3.6-3.6c-.8-.8-2-.8-2.8 0l-15 15V24h6.4l15-15zm-5-5L24 7.6l-3 3L17.4 7l3-3zM6 22v-3.6l10-10l3.6 3.6l-10 10H6z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Edit this page<!--]--></span></span></div><div class="meta-item last-updated"><span class="xicon-container left meta-item-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M26 4h-4V2h-2v2h-8V2h-2v2H6c-1.1 0-2 .9-2 2v20c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 22H6V12h20v14zm0-16H6V6h4v2h2V6h8v2h2V6h4v4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Last Updated 2024/9/22 16:35:40<!--]--></span></span></div></footer><!----><!----></div><div class="page-catalog-container"><h5 class="tip">ON THIS PAGE</h5><ul><!--[--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/OS/lab6.html#_1-思考题" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1. 思考题"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1. 思考题<!--]--></span></span><!--[--><!--]--></a></li><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-1-thinking-6-1" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.1 Thinking 6.1"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.1 Thinking 6.1<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-2-thinking-6-2" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.2 Thinking 6.2"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.2 Thinking 6.2<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-3-thinking-6-3" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.3 Thinking 6.3"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.3 Thinking 6.3<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-4-thinking-6-4" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.4 Thinking 6.4"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.4 Thinking 6.4<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-5-thinking-6-5" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.5 Thinking 6.5"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.5 Thinking 6.5<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-6-thinking-6-6" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.6 Thinking 6.6"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.6 Thinking 6.6<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-7-thinking-6-7" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.7 Thinking 6.7"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.7 Thinking 6.7<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab6.html#_1-8-thinking-6-8" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.8 Thinking 6.8"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.8 Thinking 6.8<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/OS/lab6.html#_2-难点分析" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="2. 难点分析"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2. 难点分析<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/OS/lab6.html#_3-实验体会" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="3. 实验体会"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->3. 实验体会<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--></ul></div></main><!--]--></div><!--[--><!----><!----><!--]--><!--]--></div>
<script type="module" src="/assets/app-B51tXhJU.js" defer></script>
</body>
</html>