-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
603 lines (311 loc) · 574 KB
/
atom.xml
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Heeler-Deer</title>
<link href="https://heeler-deer.top/atom.xml" rel="self"/>
<link href="https://heeler-deer.top/"/>
<updated>2024-05-07T08:18:17.733Z</updated>
<id>https://heeler-deer.top/</id>
<author>
<name>Heeler-Deer</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>wsl2安卓开发环境搭建</title>
<link href="https://heeler-deer.top/posts/57407/"/>
<id>https://heeler-deer.top/posts/57407/</id>
<published>2023-06-25T09:04:52.000Z</published>
<updated>2024-05-07T08:18:17.733Z</updated>
<content type="html"><![CDATA[<p>本篇内容主要涉及:</p><ol type="1"><li>windows安装wsl2以及wsl2安装Arch</li><li>Arch搭建node/conda/java/flutter/c++等开发环境</li><li>Android Studio使用连接windows的手机设备</li></ol><h1 id="wsl2安装">wsl2安装</h1><h3 id="为什么是wsl2">为什么是wsl2</h3><p>nvidia对linux的相关驱动已经越来越完善,越来越多的人使用linux/mac系统作为日常开发环境——而windows相较unix系系统,本身的快捷键、命令行等相关支持并不完善,所幸经过几年的完善,wsl2已经发展的比较完善了,而使用wsl2的优点在于:存在于wsl2的整个环境都可以打包,迁移方便,可以轻松管理开发环境。在我看来,这是wsl2最大的优点,尽管wsl2目前的gui程序还存在一些问题,但作为个人开发者,wsl2已经可以满足大多数开发场景了——你不需要像使用纯linux一下配置驱动、配置各种应用程序(尽管有些程序确实比windows下相应的程序好)</p><h3 id="安装wsl2">安装wsl2</h3><p>可以参考:<a href="https://gitee.com/regentsai/wsl_arch_kde">wsl2+archlinux+kde+tigerVNC图形化配置:漫长的折腾以后完成了wsl2下archlinux的安装和kde桌面的图形化显示。以此记录。(gitee.com)</a></p><p>在微软商店中,直接搜索wsl安装即可获得wsl1,这个时候,我们以管理员模式打开powershell,输入:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux<br></code></pre></div></td></tr></tbody></table></figure><p>重启wsl,再次输入:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart<br>dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart<br>wsl --set-default-version 2<br></code></pre></div></td></tr></tbody></table></figure><p>即可设置为wsl2.</p><p>这个时候,在微软商店中安装arch即可。注意,我们不需要为wsl2配置图形化界面,只需要安装好中文即可。按照我的体验,不建议使用vnc作为图形界面,不如直接终端启动wsl2的图形化程序。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/jpg/202306271648765.png" srcset="/img/loading.gif" lazyload></p><h3 id="wsl的迁移与基础配置">wsl的迁移与基础配置</h3><p>由于Arch上要装许多开发环境,占用空间越来越大,建议将wsl迁移到其他盘,可以参考<a href="https://zhuanlan.zhihu.com/p/406917270">WSL的安装和位置迁移 - 知乎(zhihu.com)</a></p><p>首先powershell中关停wsl:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">wsl --shutdown<br></code></pre></div></td></tr></tbody></table></figure><p>之后导出:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">wsl --export Arch D:/export.tar<br></code></pre></div></td></tr></tbody></table></figure><p>最后注销原来的虚拟机器卸载并导入:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">wsl --unregister Arch<br>wsl --import Arch D:\export\ D:\export.tar --version 2<br></code></pre></div></td></tr></tbody></table></figure><h4 id="配置代理">配置代理</h4><p>首先假设你的host机器能够科学上网,且在127.0.0.1:7890开了端口。那么我们在wsl2里面需要做的就是把流量引导到windows中,而我们就需要获取windows的ip:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">export hostip=$(cat /etc/resolv.conf |grep -oP '(?<=nameserver\ ).*')<br></code></pre></div></td></tr></tbody></table></figure><p>之后,可以通过命令设置https_proxy以及http_proxy的值,注意引号中的内容需要根据自己使用的协议选择http或者socks5</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">export https_proxy="http://${hostip}:7890";<br>export http_proxy="http://${hostip}:7890";<br></code></pre></div></td></tr></tbody></table></figure><p>参考 <a href="https://solidspoon.xyz/2021/02/17/%E9%85%8D%E7%BD%AEWSL2%E4%BD%BF%E7%94%A8Windows%E4%BB%A3%E7%90%86%E4%B8%8A%E7%BD%91/">代理上网</a>,可以在.bashrc/.zshrc中添加:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">export hostip=$(cat /etc/resolv.conf |grep -oP '(?<=nameserver\ ).*')<br>alias setss='export all_proxy="socks5://${hostip}:7890";'<br>alias unsetss='unset all_proxy'<br></code></pre></div></td></tr></tbody></table></figure><p>这个时候,尽管我们可以通过setss让终端科学上网,但无法让wsl2的其他程序上网,这里可以使用proxychains4,配置后即可通过proxychains4program来让程序也科学上网。</p><h1 id="arch开发环境搭建">Arch开发环境搭建</h1><p>建议先使用pacman安装yay,之后使用yay安装其他软件即可:</p><figure class="highlight vala"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vala"><span class="hljs-meta"># 初始化</span><br><span class="hljs-meta">## 设置root密码</span><br>passwd<br>pacman-key --init<br>pacman-key --populate<br>pacman -S archlinuxcn-keyring<br> <br><span class="hljs-meta"># 更新</span><br>pacman -Syyu<br> <br><span class="hljs-meta"># 安装基本软件</span><br>pacman -S base base-devel git curl wget zsh yay neofetch net-tools dnsutils inetutils<br></code></pre></div></td></tr></tbody></table></figure><h1 id="android-studio相关配置">Android Studio相关配置</h1><p>首先,在wsl2中使用gui程序,有时是会直接卡死的,因此要做好心理准备<span class="github-emoji"><span>😃</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f603.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><p>安装的androidstudio的话,非常简单,官网下载包就行,执行文件在./AndroidStudio/bin下的studio.sh。我的做法是将该路径添加到/etc/profile的path环境变量中,这些source/etc/profile后就可以在任意路径执行studio.sh了。</p><p>Android Studio的使用和windows/mac基本一致,不在详述。</p><p>关于安卓代码调试,在我的环境中,AndroidStudio不支持创建虚拟设备,因此只能选择物理真机调试,此时需要做一个网络端口转发才能让wsl2的androidstudio连接到物理机。</p><p>首先,windows安装adb并将其添加到环境变量中,将手机连接后,在powershell中执行</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">adb devices<br></code></pre></div></td></tr></tbody></table></figure><p>可以看到连接windows的设备。</p><p>此时,在wsl2的arch中安装adb,执行:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">adb devices<br></code></pre></div></td></tr></tbody></table></figure><p>这个时候应该看不到手机(该终端未执行setss时)</p><p>而为了让wsl2能够看到手机,我们需要主机的ip,由于在前述中,我们设置了hostip用于保存windows的ip,因此此时我们可以通过执行:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">setss<br>adb devices<br></code></pre></div></td></tr></tbody></table></figure><p>来看到手机,<strong>或者</strong>通过修改proxychains4的配置文件,执行:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">proxychains4 adb devices<br></code></pre></div></td></tr></tbody></table></figure><p>来看到手机。而要想让Android Studio在devicemanager中看到手机,只需要执行:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">proxychians4 studio.sh<br></code></pre></div></td></tr></tbody></table></figure><p>即可。注意,这里不推荐手动填写配置AS的代理设置,通过proxychains4更加方便。</p><p>这里可能会出现问题,由于使用了proxychains4做代理,笔者在开发flutter项目时,发现尽管通过proxychains4启动AndroidStudio可以使其识别设备,在编译运行安卓时却会由于代理混乱导致无法编译成功,报错类似:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">A new daemon was started but could not be connected to: pid=DaemonInfo{pid=4632, address=[85bbb456-d4ea-4e7e-9e29-5b7f8dc768e8 port:35581, addresses:[/127.0.0.1]], state=Busy, lastBusy=1687741775718, context=DefaultDaemonContext[uid=dcfbca72-8331-4ca2-a9b9-8c64eabd7832,javaHome=/home/heelerdeer/Desktop/android-studio/jbr,daemonRegistryDir=...<br></code></pre></div></td></tr></tbody></table></figure><h3 id="调试和开发">调试和开发</h3><p>关于如何在wsl2调试开发安卓,我目前的解决办法是在外部的powershell终端使用代理启动AS,这样在调试时可以直接使用AS的logcat查看日志。编译程序时则在外部终端手动执行命令编译成apk文件(不使用代理),然后使用adb安装到手机上(使用代理运行adb)。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/jpg/202307172351583.png" srcset="/img/loading.gif" lazyload></p><p>这时候在使用代理开启adb,安装apk,并使用代理开启androidstudio(使其可以扫描到手机),打开其logcat,输入对应的安装包包名,即可看到手机上app的运行日志:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/jpg/202307172353834.png" srcset="/img/loading.gif" lazyload></p><h1 id="参考">参考</h1><p><a href="https://gitee.com/regentsai/wsl_arch_kde">wsl2+archlinux+kde+tigerVNC图形化配置:漫长的折腾以后完成了wsl2下archlinux的安装和kde桌面的图形化显示。以此记录。(gitee.com)</a></p><p><a href="https://solidspoon.xyz/2021/02/17/%E9%85%8D%E7%BD%AEWSL2%E4%BD%BF%E7%94%A8Windows%E4%BB%A3%E7%90%86%E4%B8%8A%E7%BD%91/">代理上网</a></p><p><a href="https://zhuanlan.zhihu.com/p/406917270">WSL的安装和位置迁移- 知乎 (zhihu.com)</a></p><p><a href="https://www.cnblogs.com/lentikr/p/16433148.html">WSL2+ArchLinux环境配置- lentikr - 博客园 (cnblogs.com)</a></p><h1 id="声明">声明</h1><p>我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2899caoptmo0k</p>]]></content>
<summary type="html"><p>本篇内容主要涉及:</p>
<ol type="1">
<li>windows安装wsl2以及wsl2安装Arch</li>
<li>Arch搭建node/conda/java/flutter/c++等开发环境</li>
<li>Android Studio使用连接wind</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="https://heeler-deer.top/posts/4a17b156/"/>
<id>https://heeler-deer.top/posts/4a17b156/</id>
<published>2023-06-23T16:27:03.732Z</published>
<updated>2023-09-28T08:08:20.128Z</updated>
<content type="html"><![CDATA[<p>Hello,world!</p>]]></content>
<summary type="html"><p>Hello,world!</p>
</summary>
</entry>
<entry>
<title>RAFT && 6.824_lab2</title>
<link href="https://heeler-deer.top/posts/49939/"/>
<id>https://heeler-deer.top/posts/49939/</id>
<published>2023-03-08T12:27:10.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="设计">设计</h1><p>Raft是著名的状态机类型的协议,他通过在多个服务器之间确定leader,保证了服务器之间对于一对key-value的<strong>consensus</strong>,可以通过这个<a href="http://thesecretlivesofdata.com/raft/">可视化动画</a>来理解raft</p><p>在6.824要求阅读的<a href="https://pdos.csail.mit.edu/6.824/papers/raft-extended.pdf">论文</a>中,有一个关于raft服务器的状态机图:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303082122769.png" srcset="/img/loading.gif" lazyload style="zoom: 50%;"></p><p>lab2要求我们实现一个raft.具体编码工作在./src/raft/raft.go里面</p><p>lab2a要求我们实现raft里面的leaderelection。显然,我们需要着重于以下几点:</p><ol type="1"><li>状态机的实现</li><li>心跳机制</li></ol><h1 id="debug技巧">Debug技巧</h1><p>在编写代码之前,需要先学习debug的一些技巧。</p><p>对于多线程应用,断点调试是几乎不可能的。我们应该将重点放在log的输出上。然而过多的log不利于我们查看并追踪,在<a href="https://thesquareplanet.com/blog/students-guide-to-raft/">Students'Guide to Raft</a>以及<a href="https://blog.josejg.com/debugging-pretty/">Debugging by PrettyPrinting</a>有介绍一些可能用到的技巧以及可能犯下的错误。</p><p>十分建议直接使用<a href="https://blog.josejg.com/debugging-pretty/">Debugging by PrettyPrinting</a>里面的代码,里面提到的技巧如下:</p><ul><li>切换输出详细程度</li><li>输出log时标注相关主体</li><li>打印项目内部需要的重要信息,如调用print的函数</li></ul><p>初次之外,TA还使用python根据log的类别,VERBOSE=1更改了log的颜色,使之更容易阅读</p><p>在你阅读完上述材料后,你的代码目录里至少多了TA提供的两个python文件,并且更改了src/raft/util.go</p><p>具体使用效果类似下方:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303131530910.png" srcset="/img/loading.gif" lazyload></p><h1 id="代码实现">代码实现</h1><p>首先, <strong>完全参照</strong> 论文,实现对应的结构体</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303082201762.png" srcset="/img/loading.gif" lazyload style="zoom:25%;"></p><h2 id="lab2a">Lab2A</h2><p>Lab2A要求实现leader的election机制。我们先来看raft结构体,要实现论文中的选举机制,我们至少需要保存以下信息:</p><ul><li>Leaderid</li><li>当前term id</li><li>心跳时间以及选举时间</li><li>日志中已经提交确定的最大一个id号</li><li>状态机的最大日志id</li><li>将要发送的下一个日志id</li><li>已经匹配的最大日志id</li><li>当前raft的状态,即figure 4里面的三种状态</li></ul><p>这些都对应于上图中state部分的内容。与之对应的,我们需要实现以下几类函数:</p><ul><li>与选举时间、心跳时间对应的设置函数(需要为随机值,否则会出现永远无法选举出leader的情况)</li><li>论文中提到的AppendEntries以及RequestVote RPC方法</li><li>检测term是否对应的函数</li><li>选举、心跳机制</li></ul><h3 id="时间相关">时间相关</h3><p>先来看时间相关的函数。</p><p>我们有两个需要进行倒计时的时间要素,其中倒计时时间需要满足electiontime>heartbeattime,同时两个时间需要是随机化的。至少有三个函数,分别能够返回随机化的electiontime,heartbeat time以及用于提示raft这两个时间是否超时的函数。</p><h3 id="appendentries-rpc-requestvote-rpc">AppendEntries RPC &&RequestVote RPC</h3><p>这一部分仍需要参照论文,具体内容不再解释</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303131513279.png" srcset="/img/loading.gif" lazyload style="zoom:25%;"></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303131514742.png" srcset="/img/loading.gif" lazyload style="zoom:25%;"></p><h3 id="term相关">Term相关</h3><p>在figure 4里面,和term相关的内容有:</p><ul><li>假如leader发现一个服务器有更高的term(更高的term意味着这个leader本身由于partition等原因落后于raft集群当前选举出来的leader),就将自己转为follower,选举倒计时结束后变为candidate开始选举</li><li>假如candidate发现了leader或者新的term,就转为leader的follower.</li></ul><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303082122769.png" srcset="/img/loading.gif" lazyload style="zoom:25%;"></p><h3 id="选举心跳机制">选举、心跳机制</h3><p>这一部分需要注意各种条件的判断,其他的按照流程实现即可</p><p>成功通过后,我们将看到console输出如下信息一个:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303131529453.png" srcset="/img/loading.gif" lazyload></p><h2 id="lab-2blab2c">LAB 2B&&Lab2C</h2><p><del>最近太忙了,没动力写了</del></p><p>lab2B要求我们实现appendentries,这里需要提示的是,如果你的lab2A已经通过而lab2B/2C始终无法通过,那么很有可能是你的lab2A某些地方的判断条件写错了,这里建议仔细检查lab2A的每一个判断条件。</p><p>首先审视raft.go找到需要我们完成的函数,首先是start,这个函数注释已经把条件写的很清楚了,照着注释写即可。</p><p>其次是由于我们需要将日志里面的内容应用到机器上,因此我们需要一个能够处理appendlog并将其应用的函数applylogs,这个函数需要在传入的raft结构体未被杀死的情况下,一直访问该结构体的日志,并将其应用,同时,我们可以想到两点,一个是访问日志时需要加锁,另一个则是官网上也给出的提示:在每次应用完日志后等待一段时间。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303301451306.png" srcset="/img/loading.gif" lazyload alt="image-20230330145127910" style="zoom:25%;"></p><p>lab2C要求我们实现持久化。实验代码里面已经给出了可以直接实现持久化的persister.go,里面通过状态机和快照机制实现持久化,我们编写代码时直接调用即可。我们需要做的就是处理好持久化(恢复)的时机、序列化以及反序列化。</p><p>先看序列化以及反序列化,实验代码提供了labgob编码器以供使用,直接对需要(反)序列化的数据使用labgob.NewDecoder/NewEncoder即可</p><p>按照论文里面的内容,我们需要对log,currentTrem,votedFor这三个变量进行持久化操作,仔细检查之前的代码,这三个变量有更改操作时进行持久化即可。而在机器重启时,我们进行持久化恢复操作即可。</p><p>除此之外,在Hint里面提到,</p><blockquote><ul><li>You will probably need the optimization that backs up nextIndex bymore than one entry at a time. Look at the <a href="http://nil.csail.mit.edu/6.824/2020/papers/raft-extended.pdf">extendedRaft paper</a> starting at the bottom of page 7 and top of page 8(marked by a gray line). The paper is vague about the details; you willneed to fill in the gaps, perhaps with the help of the 6.824 Raftlectures.</li></ul></blockquote><p>这个就是为了防止一条条回退太慢。同步时,</p><ol type="1"><li>leader发现冲突位置的term自己有,就从该term的最后一个日志开始同步,</li><li>冲突位置term没有,就从该term第一个日志开始同步</li><li>同步的位置不存在,leader就回退到被同步节点的尾部开始同步</li></ol><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303301512191.png" srcset="/img/loading.gif" lazyload alt="image-20230330151258781" style="zoom:25%;"></p>]]></content>
<summary type="html"><h1 id="设计">设计</h1>
<p>Raft是著名的状态机类型的协议,他通过在多个服务器之间确定leader,保证了服务器之间对于一对key-value的<strong>consensus</strong>,可以通过这个<a href="http://thesecret</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="distributed_systems" scheme="https://heeler-deer.top/tags/distributed-systems/"/>
</entry>
<entry>
<title>MIT6.824-1</title>
<link href="https://heeler-deer.top/posts/2222/"/>
<id>https://heeler-deer.top/posts/2222/</id>
<published>2023-02-25T16:19:44.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="阅读须知">阅读须知</h1><p>MIT6.824的实验难度较大,且据我推测是每年都会有改动。学习6.824的正确姿势应该是先去观看公开课,找到官方的课程时间安排表,里面附带学习资料。即在阅读论文后上课、上完公开课后在做实验。</p><p>实验的具体完成时间可以参看课程时间安排表的due</p><p>如果你不会go,强烈建议在<a href="https://go.dev/doc/">Go</a>学习go,语法简单,很快就能学会的。</p><h1 id="环境搭建">环境搭建</h1><p>推荐视频:<a href="https://www.bilibili.com/video/BV1x7411M7Sf/">b站</a></p><p>2020课程时间安排表: <a href="http://nil.csail.mit.edu/6.824/2020/schedule.html">MIT</a></p><p>实验代码仓库:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">git clone git://g.csail.mit.edu/6.824-golabs-2020 6.824<br></code></pre></div></td></tr></tbody></table></figure><p>实验采用的开发语言为go,建议在<strong>linux</strong>下开发,同时建议使用goland这个<strong>IDE</strong>,go的环境手动配置还是有点麻烦的</p><p>当然,我选择在万能的vscode上开发——个人认为vscode的Go插件做的还是很不错的。</p><p>vscode配置go建议参考:<a href="https://zhuanlan.zhihu.com/p/320343679">知乎</a></p><p>注意go升级环境时需要将旧版本全部删除在覆盖到原先的路径下。新旧版本同时存在容易出错。</p><p>下载实验代码后目录结构如下:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303052241713.png" srcset="/img/loading.gif" lazyload alt="" style="zoom:25%;"></p><h1 id="map-and-reduce">Map and Reduce</h1><p>该实验要求我们实现一个统计单词数量的系统,该系统具有<strong>一个master,多个worker</strong>,master执行调度工作,worker执行mapand reduce工作。具体要求可查看lab1的<a href="http://nil.csail.mit.edu/6.824/2020/labs/lab-mr.html">实验指导要求</a></p><p>其中,map作用为统计每个文件的各自单词数量,reduce则将map的结果整合起来,如下图:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303052311732.png" srcset="/img/loading.gif" lazyload style="zoom:50%;"></p><p>我们首先按照指导书所示,测试环境能否运行代码里已有的文件:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">生成wc.so文件,此文件用于统计单词数量,后续也需要wc.so</span><br>go build -buildmode=plugin ../mrapps/wc.go<br><span class="hljs-meta"></span><br><span class="hljs-meta">#</span><span class="bash">删除mr-out开头的文件</span><br>rm mr-out*<br><span class="hljs-meta"></span><br><span class="hljs-meta">#</span><span class="bash">以连续的map_reduce方式统计pg*开头的文本文件的单词,此次运行生成的文件即后续测试lab1是否正确的标准</span><br>go run mrsequential.go wc.so pg*.txt<br><span class="hljs-meta"></span><br><span class="hljs-meta">#</span><span class="bash">查看生成的文件</span><br>more mr-out-0<br></code></pre></div></td></tr></tbody></table></figure><p>如果一切正常,就可以看到:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303052251926.png" srcset="/img/loading.gif" lazyload style="zoom:25%;"></p><p>之后,指导书讲解了检验我们代码运行正确与否的方式。</p><p>./src/main/mrmaster.go会调用我们实现的./src/mr/master.go文件</p><p>./src/main/mrworker.go则会调用我们实现的./src/mr/worker.go文件</p><p>我们的代码编写工作都在./src/mr里面</p><p>显然,实验一的重点在于如何设计master,worker,使得master在调度多个worker时能够无误的分配mapand reduce任务。</p><p>这对于master的要求为:</p><ol type="1"><li>两个分别对应map,reduce的结构体,存储执行该任务的文件id、worker的id。考虑到任务执行需要设置一个超时时间,还需要记录该任务对应的开始时间</li><li>一个从map转换到reduce的函数</li><li>map以及reduce对应的用于分配任务的函数,使worker能够参与任务的函数</li><li>考虑到系统稳健性,需要一个删除超时任务的函数</li></ol><p>对于worker,需要考虑以下几点:</p><ol type="1"><li>分别对应于map,reduce的请求任务、参与任务、执行任务函数</li><li>写入文件的函数</li></ol><p>考虑到master和worker通过rpc通信,还需要满足对应于rpc的调用函数</p><h2 id="master">Master</h2><p>master需要存储map以及reduce任务,我们需要一个<strong>一一对应</strong>的数据结构(存储fileid以及总数),不仅如此,还要存储该fileid对应的任务是否完成,即:</p><figure class="highlight go"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs go"><span class="hljs-keyword">type</span> MAPSET <span class="hljs-keyword">struct</span> {<br>mapbool <span class="hljs-keyword">map</span>[<span class="hljs-keyword">interface</span>{}]<span class="hljs-keyword">bool</span> <span class="hljs-comment">//fileid对应的bool的T/F表示该fileid是否完成</span><br>count <span class="hljs-keyword">int</span> <span class="hljs-comment">//总数</span><br>}<br></code></pre></div></td></tr></tbody></table></figure><p>上述结构体只能用于存储已完成的map/reduce任务信息,因为对于未完成的任务,出于稳健性考虑,我们需要一个满足线性出入的数据结构——stack,queue或者链表。分配任务时,必须加锁,虽然将锁加在数据结构里容易导致外部代码未加锁时程序死锁(讲师原话——程序员必须在需要用到锁的地方有意识的加锁而不是依赖数据结构的锁),但考虑到这是我们自己实现的数据结构,我们可以直接将锁加入里面。</p><figure class="highlight go"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs go"><span class="hljs-comment">//伪码</span><br><span class="hljs-keyword">type</span> STACK <span class="hljs-keyword">struct</span>{<br> mutex *Mutex<br> stack *Stack<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>那么对于master,我们的数据结构将被设计为:</p><figure class="highlight go"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs go"><span class="hljs-comment">//伪码</span><br><span class="hljs-keyword">type</span> Master <span class="hljs-keyword">struct</span>{<br> filenames []<span class="hljs-keyword">string</span> <span class="hljs-comment">//所有文件</span><br> cur_worker_id <span class="hljs-comment">//当前worker的id</span><br> map_done <span class="hljs-keyword">bool</span> <span class="hljs-comment">//map完成与否</span><br> reduce_done <span class="hljs-keyword">bool</span> <span class="hljs-comment">//reduce完成与否</span><br> unsolved_map_tasks *STACK<br> solved_map_task *MAPSET<br> unsolved_reduce_tasks *STACK<br> solved_reduce_task *MAPSET<br> mutex *Mutex <span class="hljs-comment">//锁</span><br> map_task_begin_second <span class="hljs-keyword">int</span> <span class="hljs-comment">//开始时间</span><br> map_task_file_id <span class="hljs-keyword">int</span> <span class="hljs-comment">//文件id</span><br> map_task_worker_id <span class="hljs-keyword">int</span> <span class="hljs-comment">//worker id</span><br> reduce_task_begin_second <span class="hljs-keyword">int</span><br> reduce_task_file_id <span class="hljs-keyword">int</span><br> reduce_task_worker_id <span class="hljs-keyword">int</span><br>}<br></code></pre></div></td></tr></tbody></table></figure><p>以map为例,我们着重介绍分配任务、加入任务以及从map转换到reduce这三个函数</p><p>考虑分配map任务,我们需要考虑以下几点:</p><ol type="1"><li>任务已经完成,则发送mapdone的消息同时释放锁(有请求则需要先加锁在判断)</li><li>任务刚好完成,则调用前文第二点提到的map到reduce转换函数,释放锁</li><li>可以分配任务,记录数据,分配任务</li></ol><p>对于加入map任务,则需要考虑任务是否超时,是否能够分配</p><p>对于从map到reduce的转换函数,我们只需要将fileid加入unsolved_reduce_task对应的结构体即可</p><h2 id="worker">Worker</h2><p>对于worker,我们需要一个结构体存储其id,是否完成、进行map/reduce,对应于map/reduce的函数,同时,对于map/reduce,我们需要各自的请求、参与、执行函数,此处不再细讲。</p><h1 id="debugtest">Debug&Test</h1><p>由于该实验内容较多,因此我建议在master,worker的每一个函数的每一个分支内部加入输出语句,便于定位错误。</p><p>如<code>log.Printf("all map tasks Done,do reduce tasks")</code>,同时,在调用测试脚本之前,先在src/main目录下,执行以下语句:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">将master的输出写入master.txt文件</span><br>go run mrmaster.go pg-*.txt 1&>master.txt<br><span class="hljs-meta"></span><br><span class="hljs-meta">#</span><span class="bash">生成wc.so,每次都要执行</span><br>go build -buildmode=plugin ../mrapps/wc.go<br><span class="hljs-meta"></span><br><span class="hljs-meta">#</span><span class="bash">执行worker,将输出写入worker.txt文件</span><br>go run mrworker.go wc.so 1&> worker.txt<br></code></pre></div></td></tr></tbody></table></figure><p>如果写代码时加入的print语句够多,应该可以看到文件依次被送入channel,worker请求任务、完成任务,执行reduce的过程。</p><p>最后就可以执行./src/main/test-mr.sh的内容来判断是否完成实验一了:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">./test-mr.sh > test-mr.out<br></code></pre></div></td></tr></tbody></table></figure><p>成功通过就会显示下图内容:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202303060014316.png" srcset="/img/loading.gif" lazyload style="zoom:50%;"></p><h1 id="感受">感受</h1><p>才做完第一个lab就感受到了mit对学生工程能力的要求,<span class="github-emoji"><span>😜</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f61c.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><p>我从不会go到完成这个lab的过程可太折磨了,尤其是面对bug找了半天解决方案还是没找到的时候(<del>最后发现数据结构写错了</del>)</p><p>这个实验给我带来的收获就是:</p><ul><li>设计很重要,写代码先设计好框架</li><li>细节也很重要</li><li>写工程时要注意log的输出</li></ul><h1 id="参考资料">参考资料</h1><ul><li>https://zhuanlan.zhihu.com/p/260470258</li></ul>]]></content>
<summary type="html"><h1 id="阅读须知">阅读须知</h1>
<p>MIT
6.824的实验难度较大,且据我推测是每年都会有改动。学习6.824的正确姿势应该是先去观看公开课,找到官方的课程时间安排表,里面附带学习资料。即在阅读论文后上课、上完公开课后在做实验。</p>
<p>实验的具体完成时</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="distributed_systems" scheme="https://heeler-deer.top/tags/distributed-systems/"/>
</entry>
<entry>
<title>socks5</title>
<link href="https://heeler-deer.top/posts/46421/"/>
<id>https://heeler-deer.top/posts/46421/</id>
<published>2022-12-31T08:28:50.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<p>自己搭建vps服务器建议参考我之前的<a href="https://heeler-deer.github.io/2021/11/13/vps/">博客</a></p><p>本文主要参考<a href="https://cloud.tencent.com/developer/article/1852590">Rokas.Yang</a>。</p><p>针对国内云服务器无法使用github这一问题(如今各大运营商已经将github屏蔽),我的建议是尽早在服务器上使用代理。</p><h1 id="shadowsocksr">shadowsocksr</h1><p>软件安装,首先在本机下载软件<a href="https://github.com/RokasUrbelis/shadowsocksr">shadowsocksr</a></p><p>之后传输到服务器上。</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">解压</span><br>unzip sh*.zip<br><span class="hljs-meta">#</span><span class="bash">进入目录</span><br>cd sha*r<br><span class="hljs-meta">#</span><span class="bash">执行初始化脚本</span><br>sh initcfg.sh<br><span class="hljs-meta">#</span><span class="bash">更改配置文件</span><br>vim config.json<br></code></pre></div></td></tr></tbody></table></figure><p>配置文件具体内容按照代理的选项填充即可。</p><p>为了以后方便使用代理,建议将本地端口local port选项映射到2000</p><p>同时为了管理方便,将ssr通过systemctl进行管理</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">创建文件</span><br>mkdir -p ~/.config/systemd/user<br></code></pre></div></td></tr></tbody></table></figure><p>启动ssr代理需要三个选项:</p><ul><li>python运行环境</li><li>shadowsocksr/shadowsocks/local.py(即下载的目录里面的文件)</li><li>刚刚填写的配置文件config.json</li></ul><p>这里建议python为3.7及以上。</p><p>首先查询python运行环境,</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">此处查询服务器python位置</span><br>whereis python<br></code></pre></div></td></tr></tbody></table></figure><p>之后可以填写systemd的服务文件,<code>vim ~/.config/systemd/user/ssr-client.service</code></p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">[Unit]<br>Description=Shadowsocks R Client Service<br>After=default.target<br>[Service]<br>ExecStart=/usr/local/python/bin/python3.10 /root/shadowsocksr-manyuser/shadowsocks/local.py -c /root/shadowsocksr-manyuser/user-config.json #以你实际路径为准<br>Restart=on-abort<br>[Install]<br>WantedBy=default.target<br></code></pre></div></td></tr></tbody></table></figure><p>之后即可通过systemd管理服务:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">重载服务</span><br>systemctl --user daemon-reload<br><span class="hljs-meta">#</span><span class="bash">启动ssr</span><br>systemctl --user start ssr-client<br><span class="hljs-meta">#</span><span class="bash">查看运行状态</span><br>systemctl --user status ssr-client<br><span class="hljs-meta">#</span><span class="bash">设置为开机启动</span><br>systemctl --user enable ssr-client<br></code></pre></div></td></tr></tbody></table></figure><h1 id="proxychains4">proxychains4</h1><p>为了更方便调用ssr代理,需要安装proxychains4</p><p>还是在本机电脑开代理下载<a href="https://github.com/rofl0r/proxychains-ng.git">proxychains4</a>,之后传输到服务器,</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash">解压</span><br>unzip pro*.zip<br><span class="hljs-meta">#</span><span class="bash">进入目录</span><br>cd proxychains-ng<br><span class="hljs-meta">#</span><span class="bash">安装</span><br>./configure<br>make && sudo make install<br><span class="hljs-meta">#</span><span class="bash">复制配置文件</span><br>sudo cp ./src/proxychains.conf /etc/proxychains.conf<br><span class="hljs-meta">#</span><span class="bash">编辑配置文件</span><br>sudo vim /etc/proxychains.conf<br></code></pre></div></td></tr></tbody></table></figure><p>由于刚刚已经把ssr的本地端口设置为2000,因此只需要把最后一行设置为socks5127.0.0.1 2000即可。</p><p>检测是否能够使用代理,可以尝试curl一下google</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">proxychains4 curl www.google.com<br></code></pre></div></td></tr></tbody></table></figure><p>正常情况会返回如下所示的内容:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202212311712638.png" srcset="/img/loading.gif" lazyload></p><h1 id="issuses">issuses</h1><p><strong>问题一</strong></p><p>执行systemctl --user daemon-reload时报错:</p><p><span class="github-emoji"><span>☠</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/2620.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span> Failed to get D-Bus connection: No such fileor directory</p><p>这个问题,在我的centos(uname -r查看版本为3.10.0-1160.80.1.el7.x86_64)上可以通过去掉--user选项解决。网上说高版本的centos不会出错。</p><p><strong>问题二</strong></p><p>执行systemctl --user daemon-reload时报错:service not found</p><p>这个问题其实还是centos的版本问题,建议有root权限的话直接将文件ssr-client.service编写在/usr/lib/systemd/system下面。</p>]]></content>
<summary type="html"><p>自己搭建vps服务器建议参考我之前的<a href="https://heeler-deer.github.io/2021/11/13/vps/">博客</a></p>
<p>本文主要参考<a href="https://cloud.tencent.com/develope</summary>
<category term="瞎搞" scheme="https://heeler-deer.top/categories/%E7%9E%8E%E6%90%9E/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="花里胡哨" scheme="https://heeler-deer.top/tags/%E8%8A%B1%E9%87%8C%E8%83%A1%E5%93%A8/"/>
</entry>
<entry>
<title>email_in_cs</title>
<link href="https://heeler-deer.top/posts/5799/"/>
<id>https://heeler-deer.top/posts/5799/</id>
<published>2022-09-23T09:51:12.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="前言">前言</h1><p>毕竟以前没搭建过邮件服务器,挺有意思的。记录一下,本篇<strong>不能</strong>作为指导性博客使用。</p><p>由于邮件发送的流程是:</p><pre><code class="mermaid" type="">flowchart LRa([用户A])b([用户B])a_t((a_thunderbird))b_t((b_thunderbird))a_g[(a_gmail)]b_q[(b_qqmail)]a--撰写邮件-->a_t--发送至邮件服务器-->a_g--交互-->b_q--发送给b-->b_t-->b</code></pre><p>而课程最终是要实现一个邮件的user agent——MUA以及一个邮件的TransferAgent——MTA。</p><p>相当于要实现一个smtp服务器以及一个能够阅读邮件的客户端。</p><p>现在看来还要改协议了</p><h1 id="服务器端">服务器端</h1><h2 id="服务器以及使用软件">服务器以及使用软件</h2><p>云服务器选择上,我选择了腾讯云2核4G的服务器,70多能白嫖一年;而且毕竟就跑一个邮箱服务器应该要不了多大配置,其他类型的服务器说实话有点贵。位置选择的香港的,不喜欢内陆的节点(</p><p>记得申请域名</p><p>操作系统选择的centos,整天用debian系的,总要换换口味</p><p>为了方便以后使用服务器,我写了一个oh-my-zsh的一键配置脚本:</p><p><a href="https://github.com/heeler-deer/zsh">Github</a></p><p>使用时直接clone后运行config.sh即可,不过里面有下载github的软件,建议香港等地的服务器可以考虑使用。</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">yum install git<br>git clone https://github.com/heeler-deer/zsh.git<br>sh ./zsh/config.sh<br>cp ./zsh/zshrc.txt ./.zshrc<br>source ./zshrc<br></code></pre></div></td></tr></tbody></table></figure><p>之后</p><p>至于使用的软件,我选择的是:</p><ul><li>Postfix ,即MTA,负责smtp协议相关内容</li><li>Dovecot ,负责 IMAP/POP协议相关内容</li></ul><p>接下来安装即可,</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">yum install postfix<br>yum install dovecot<br>yum remove sendmail<br></code></pre></div></td></tr></tbody></table></figure><p>开启postfix/dovecot:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">systemctl start postfix<br>systemctl enable postfix<br>systemctl start dovecot<br>systemctl enable dovecot<br></code></pre></div></td></tr></tbody></table></figure><h2 id="相关配置">相关配置</h2><p>目前配置的文件是这几个:</p><ul><li>/etc/postfix/main.cf</li><li>/etc/dovecot/conf.d/10-mail.conf</li><li>/etc/dovecot/dovecot.conf</li><li>/etc/dovecot/conf.d/10-auth.conf</li></ul><p>我已经做了<a href="https://github.com/heeler-deer/absorbing/tree/main/mail">备份</a>,这样下次就不用在重新配置了<span class="github-emoji"><span>😄</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f604.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><p>注意/etc/postfix/main.cf里面的xxxx换成自己的域名</p><p>具体更改可以参考<a href="https://www.open-open.com/lib/view/open1431592348122.html#articleHeader16">文章</a></p><p>最后还更改了/etc/hosts的内容:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">127.0.0.1 mail.xxxx<br>127.0.0.1 localhost.localdomain localhost<br>127.0.0.1 localhost4.localdomain4 localhost4<br>127.0.0.1 localhost mail.xxxx localhost.localdomain localhost4 localhost4.localdomain4<br>::1 mail.xxxx ip_of_xxxx<br>::1 localhost.localdomain localhost<br>::1 localhost6.localdomain6 localhost6<br></code></pre></div></td></tr></tbody></table></figure><h1 id="参考链接">参考链接</h1><p>主要流程:</p><ul><li>http://static.kancloud.cn/a173512/php_note/1690621</li><li>https://www.jianshu.com/p/502f23489dd4</li><li>https://www.open-open.com/lib/view/open1431592348122.html</li><li>http://www.jinyazhou.com/16327296817407.html</li><li>http://doc.ewomail.com/docs/ewomail/install</li></ul><p>其他细节参考:</p><ul><li>https://blog.51cto.com/u_9955199/3226094</li><li>https://serverfault.com/questions/561507/postfix-tls-authentication-not-enabled</li><li>https://serverfault.com/questions/371713/unable-to-telnet-into-port-25-on-centos-postfix-server</li><li>https://www.devopszones.com/2020/04/how-to-fix-postfix-relay-access-denied.html</li></ul>]]></content>
<summary type="html"><h1 id="前言">前言</h1>
<p>毕竟以前没搭建过邮件服务器,挺有意思的。记录一下,本篇<strong>不能</strong>作为指导性博客使用。</p>
<p>由于邮件发送的流程是:</p>
<pre><code class="mermaid" type="">
</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="email" scheme="https://heeler-deer.top/tags/email/"/>
</entry>
<entry>
<title>搭建gitlab</title>
<link href="https://heeler-deer.top/posts/40544/"/>
<id>https://heeler-deer.top/posts/40544/</id>
<published>2022-07-26T07:55:37.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="前言">前言</h1><p>不建议任何人在近半年内买树莓派/香橙派之类的玩具,由于芯片问题,树莓派/香橙派价格大涨。</p><p><del>除非你和我一样是纯纯冤种</del></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261601695.png" srcset="/img/loading.gif" lazyload></p><h1 id="拆盒">拆盒</h1><p>此处略过,建议阅读:</p><p><a href="https://shumeipai.nxez.com/hot-explorer#beginner">上手必读</a></p><h2 id="刷系统">刷系统</h2><p>记得买一个读卡器,大概10块钱;一般买pi都会顺便买一个tf卡,准备好这两个基本就行了。</p><p>刷卡软件我建议使用<a href="https://www.balena.io/etcher/">etcher</a>:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261605736.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261607551.png" srcset="/img/loading.gif" lazyload></p><p>之后用读卡器写入镜像就像。镜像建议从各种pi的官网下载</p><p>至于联网,我是准备了一根网线直接链接家里的网络。由于后期要做内网穿透,<strong>不建议在学校进行</strong>。</p><h2 id="连接">连接</h2><p>如果你和我一样,没有能够使用的屏幕,只能ssh链接的话,在pi第一次启动时,ssh并未自动开启,可以像我一样准备/etc/rc.lcoal:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261608366.png" srcset="/img/loading.gif" lazyload></p><p>使其能够开机后开启ssh服务。但第二次启动时需要删除25~26行,27行酌情删除</p><p>之后在路由帐号内部查看pi的ip即可。</p><p>根据需要安装桌面。</p><h1 id="搭建gitlab">搭建gitlab</h1><p>其实就是一个有图形化界面的gitlab,实际上完全可以不要gitlab的图像界面,转而使用gitcore+内网穿透的传统办法。由于我配置不行,最终卸载了gitlab(gitlab非常吃内存)</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261611129.png" srcset="/img/loading.gif" lazyload></p><p>首先去<a href="https://packages.gitlab.com/gitlab">gitlab</a>下载需要的版本,我们选择raspberry-pi2即可。必须根据pi的版本选择合适的deb包,否则可能出现glibc版本不对应的情况。<strong>glibc版本更改较为困难,不建议更改</strong>。</p><p>之后一路安装即可。</p><h1 id="内网穿透">内网穿透</h1><p>可以采取传统的工具进行穿透,也可以直接使用<a href="https://hsk.oray.com/download/">花生壳</a>:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261627011.png" srcset="/img/loading.gif" lazyload></p><p>一路安装即可,</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261628942.png" srcset="/img/loading.gif" lazyload></p><h1 id="配置邮箱">配置邮箱</h1><p>gitlab可以配置邮箱,使新用户注册时可以收到邮件。</p><p>首先根据 <a href="https://blog.51cto.com/u_15266039/4115941">blog</a>更改管理员密码</p><p>在根据 <a href="https://juejin.cn/post/6991924908242501669">blog2</a>更改配置即可。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261634666.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261634951.png" srcset="/img/loading.gif" lazyload></p><p>最后重启即可</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202207261634341.png" srcset="/img/loading.gif" lazyload></p>]]></content>
<summary type="html"><h1 id="前言">前言</h1>
<p>不建议任何人在近半年内买树莓派/香橙派之类的玩具,由于芯片问题,树莓派/香橙派价格大涨。</p>
<p><del>除非你和我一样是纯纯冤种</del></p>
<p><img src="https://raw.githubuserco</summary>
<category term="瞎搞" scheme="https://heeler-deer.top/categories/%E7%9E%8E%E6%90%9E/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
</entry>
<entry>
<title>ucore-lab7</title>
<link href="https://heeler-deer.top/posts/27963/"/>
<id>https://heeler-deer.top/posts/27963/</id>
<published>2022-05-27T13:12:49.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="练习解答">练习解答</h1><ul><li>理解操作系统的同步互斥的设计实现;</li><li>理解底层支撑技术:禁用中断、定时器、等待队列;</li><li>在ucore中理解信号量(semaphore)机制的具体实现;</li><li>理解管程机制,在ucore内核中增加基于管程(monitor)的条件变量(conditionvariable)的支持;</li><li>了解经典进程同步问题,并能使用同步机制解决进程同步问题。</li></ul><h2 id="练习0">练习0</h2><p>填写实验,自行填写,懒得找了,可以参考<a href="https://kiprey.github.io/2020/09/uCore-7/#%E7%BB%83%E4%B9%A00">kiprey</a></p><h2 id="练习一">练习一</h2><blockquote><p>理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码)</p><p>完成练习0后,建议大家比较一下(可用meld等文件diff比较软件)个人完成的lab6和练习0完成后的刚修改的lab7之间的区别,分析了解lab7采用信号量的执行过程。执行<code>make grade</code>,大部分测试用例应该通过。</p><p>请在实验报告中给出内核级信号量的设计描述,并说明其大致执行流程。</p><p>请在实验报告中给出给用户态进程/线程提供信号量机制的设计方案,并比较说明给内核级提供信号量机制的异同。</p></blockquote><p>实际上就是解释ucore的哲学家就餐怎么实现的,内核级别的信号量怎么实现的,之后给出自己关于用户级别的信号量的设计方案,比较两者异同。</p><p>关于哲学家就餐问题,不知道为什么,代码里面有注释,中文的。。。</p><p>结合注释是不难理解的。</p><p>在kern/sync/check_sync.c可以找到:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">//---------- philosophers problem using semaphore ----------------------</span><br><span class="hljs-keyword">int</span> state_sema[N]; <span class="hljs-comment">/* 记录每个人状态的数组 */</span><br><span class="hljs-comment">/* 信号量是一个特殊的整型变量 */</span><br><span class="hljs-keyword">semaphore_t</span> mutex; <span class="hljs-comment">/* 临界区互斥 */</span><br><span class="hljs-keyword">semaphore_t</span> s[N]; <span class="hljs-comment">/* 每个哲学家一个信号量 */</span><br><br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">philosopher_proc_sema</span>[<span class="hljs-title">N</span>];</span><br><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">phi_test_sema</span><span class="hljs-params">(i)</span> <span class="hljs-comment">/* i:哲学家号码从0到N-1 */</span></span><br><span class="hljs-function"></span>{ <br> <span class="hljs-keyword">if</span>(state_sema[i]==HUNGRY&&state_sema[LEFT]!=EATING<br> &&state_sema[RIGHT]!=EATING)<br> {<br> state_sema[i]=EATING;<br> up(&s[i]);<br> }<br>}<br><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">phi_take_forks_sema</span><span class="hljs-params">(<span class="hljs-keyword">int</span> i)</span> <span class="hljs-comment">/* i:哲学家号码从0到N-1 */</span></span><br><span class="hljs-function"></span>{ <br> down(&mutex); <span class="hljs-comment">/* 进入临界区 */</span><br> state_sema[i]=HUNGRY; <span class="hljs-comment">/* 记录下哲学家i饥饿的事实 */</span><br> phi_test_sema(i); <span class="hljs-comment">/* 试图得到两只叉子 */</span><br> up(&mutex); <span class="hljs-comment">/* 离开临界区 */</span><br> down(&s[i]); <span class="hljs-comment">/* 如果得不到叉子就阻塞 */</span><br>}<br><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">phi_put_forks_sema</span><span class="hljs-params">(<span class="hljs-keyword">int</span> i)</span> <span class="hljs-comment">/* i:哲学家号码从0到N-1 */</span></span><br><span class="hljs-function"></span>{ <br> down(&mutex); <span class="hljs-comment">/* 进入临界区 */</span><br> state_sema[i]=THINKING; <span class="hljs-comment">/* 哲学家进餐结束 */</span><br> phi_test_sema(LEFT); <span class="hljs-comment">/* 看一下左邻居现在是否能进餐 */</span><br> phi_test_sema(RIGHT); <span class="hljs-comment">/* 看一下右邻居现在是否能进餐 */</span><br> up(&mutex); <span class="hljs-comment">/* 离开临界区 */</span><br>}<br><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">philosopher_using_semaphore</span><span class="hljs-params">(<span class="hljs-keyword">void</span> * arg)</span> <span class="hljs-comment">/* i:哲学家号码,从0到N-1 */</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">int</span> i, iter=<span class="hljs-number">0</span>;<br> i=(<span class="hljs-keyword">int</span>)arg;<br> cprintf(<span class="hljs-string">"I am No.%d philosopher_sema\n"</span>,i);<br> <span class="hljs-keyword">while</span>(iter++<TIMES)<br> { <span class="hljs-comment">/* 无限循环 */</span><br> cprintf(<span class="hljs-string">"Iter %d, No.%d philosopher_sema is thinking\n"</span>,iter,i); <span class="hljs-comment">/* 哲学家正在思考 */</span><br> do_sleep(SLEEP_TIME);<br> phi_take_forks_sema(i); <br> <span class="hljs-comment">/* 需要两只叉子,或者阻塞 */</span><br> cprintf(<span class="hljs-string">"Iter %d, No.%d philosopher_sema is eating\n"</span>,iter,i); <span class="hljs-comment">/* 进餐 */</span><br> do_sleep(SLEEP_TIME);<br> phi_put_forks_sema(i); <br> <span class="hljs-comment">/* 把两把叉子同时放回桌子 */</span><br> }<br> cprintf(<span class="hljs-string">"No.%d philosopher_sema quit\n"</span>,i);<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; <br>}<br></code></pre></div></td></tr></tbody></table></figure><ul><li>请给出内核级信号量的设计描述,并说明其大致执行流程</li></ul><p>内核级别信号量结构体定义位于kern/sync/sem.h中:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> {</span><br> <span class="hljs-keyword">int</span> value;<br> <span class="hljs-keyword">wait_queue_t</span> wait_queue;<br>} <span class="hljs-keyword">semaphore_t</span>;<br></code></pre></div></td></tr></tbody></table></figure><p>观察哲学家就餐代码,不难发现信号量有关函数:down,up,继续查看封装的函数在kern/sync/sem.c里面,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">up</span><span class="hljs-params">(<span class="hljs-keyword">semaphore_t</span> *sem)</span> </span>{<br> __up(sem, WT_KSEM);<br>}<br><br><span class="hljs-function"><span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">down</span><span class="hljs-params">(<span class="hljs-keyword">semaphore_t</span> *sem)</span> </span>{<br> <span class="hljs-keyword">uint32_t</span> flags = __down(sem, WT_KSEM);<br> assert(flags == <span class="hljs-number">0</span>);<br>}<br><span class="hljs-comment">////////////////////////////////////////////////////////////////</span><br><span class="hljs-keyword">static</span> __noinline <span class="hljs-keyword">void</span> __up(<span class="hljs-keyword">semaphore_t</span> *sem, <span class="hljs-keyword">uint32_t</span> wait_state) {<br> <span class="hljs-keyword">bool</span> intr_flag;<br> <span class="hljs-comment">//根据intr_flag决定是否要enable irq interrupt</span><br> local_intr_save(intr_flag);<br> {<br> <span class="hljs-keyword">wait_t</span> *wait;<br> <span class="hljs-comment">//如果队列中没有wait的线程,value++</span><br> <span class="hljs-keyword">if</span> ((wait = wait_queue_first(&(sem->wait_queue))) == <span class="hljs-literal">NULL</span>) {<br> sem->value ++;<br> }<br> <span class="hljs-comment">//否则唤醒线程且执行代码</span><br> <span class="hljs-keyword">else</span> {<br> assert(wait->proc->wait_state == wait_state);<br> wakeup_wait(&(sem->wait_queue), wait, wait_state, <span class="hljs-number">1</span>);<br> }<br> }<br> local_intr_restore(intr_flag);<span class="hljs-comment">//也是封装的函数</span><br>}<br><br><span class="hljs-keyword">static</span> __noinline <span class="hljs-keyword">uint32_t</span> __down(<span class="hljs-keyword">semaphore_t</span> *sem, <span class="hljs-keyword">uint32_t</span> wait_state) {<br> <span class="hljs-keyword">bool</span> intr_flag;<br> local_intr_save(intr_flag);<br> <span class="hljs-keyword">if</span> (sem->value > <span class="hljs-number">0</span>) {<br> <span class="hljs-comment">//如果信号量>0,递减</span><br> sem->value --;<br> local_intr_restore(intr_flag);<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> }<br> <span class="hljs-comment">//如果等于0,则准备执行进程,添加至等待队列</span><br> <span class="hljs-keyword">wait_t</span> __wait, *wait = &__wait;<br> wait_current_set(&(sem->wait_queue), wait, wait_state);<br> local_intr_restore(intr_flag);<br><span class="hljs-comment">//调度算法</span><br> schedule();<br><span class="hljs-comment">//执行完就删除</span><br> local_intr_save(intr_flag);<br> wait_current_del(&(sem->wait_queue), wait);<br> local_intr_restore(intr_flag);<br><br> <span class="hljs-keyword">if</span> (wait->wakeup_flags != wait_state) {<br> <span class="hljs-keyword">return</span> wait->wakeup_flags;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><span class="hljs-comment">//local_intr_restore,如果传入的flag为true,则enable irq interrupt,继续跟踪intr_enable会发现一段汇编</span><br><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">void</span><br>__intr_restore(<span class="hljs-keyword">bool</span> flag) {<br> <span class="hljs-keyword">if</span> (flag) {<br> intr_enable();<br> }<br>}<br></code></pre></div></td></tr></tbody></table></figure><ul><li>请给出给用户态进程/线程提供信号量机制的设计方案,并比较说明给内核级提供信号量机制的异同</li></ul><p>首先,用户级别的信号量应该存储在用户空间中,但用户本身能不能操控信号量?对于一个进程的多个线程来讲,似乎可以交由进程进行信号量的管理,但对于多个进程公用的信号量来讲,我认为应该调用内核,由内核进行管理。信号量由使用信号量的代码的更高一级的代码进行管理,应该是比较好的,至少应该抽象出更高的一个层级去管理。但考虑到信号量涉及到的同步问题,完全有内核进行原子性的操作会更好一点。</p><p>那么,怎么云实现呢?可以在proc的结构体里面增加信号量的相关代码,用于获取信号量的值,发出增加或减少信号量的请求,再由操作系统实现。详细可以参考kiprey,他参考了linux的实现。</p><h2 id="练习二">练习二</h2><blockquote><p>练习2:完成内核级条件变量和基于内核级条件变量的哲学家就餐问题(需要编码)</p><p>首先掌握管程机制,然后基于信号量实现完成条件变量实现,然后用管程机制实现哲学家就餐问题的解决方案(基于条件变量)。</p><p>执行:<code>make grade</code>。如果所显示的应用程序检测都输出ok,则基本正确。如果只是某程序过不去,比如matrix.c,则可执行</p><figure class="highlight gauss"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs gauss"><span class="hljs-built_in">make</span> <span class="hljs-keyword">run</span>-<span class="hljs-keyword">matrix</span><br></code></pre></div></td></tr></tbody></table></figure><p>命令来单独调试它。大致执行结果可看附录。</p><p>请在实验报告中给出内核级条件变量的设计描述,并说明其大致执行流程。</p><p>请在实验报告中给出给用户态进程/线程提供条件变量机制的设计方案,并比较说明给内核级提供条件变量机制的异同。</p><p>请在实验报告中回答:能否不用基于信号量机制来完成条件变量?如果不能,请给出理由,如果能,请给出设计说明和具体实现。</p></blockquote><p>在kern/sync/monitor.h中,有相关结构体,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">monitor</span> <span class="hljs-title">monitor_t</span>;</span><br><br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">condvar</span>{</span><br> <span class="hljs-keyword">semaphore_t</span> sem; <span class="hljs-comment">// the sem semaphore is used to down the waiting proc, and the signaling proc should up the waiting proc</span><br> <span class="hljs-keyword">int</span> count; <span class="hljs-comment">// the number of waiters on condvar</span><br> <span class="hljs-keyword">monitor_t</span> * owner; <span class="hljs-comment">// the owner(monitor) of this condvar</span><br>} <span class="hljs-keyword">condvar_t</span>;<br><br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">monitor</span>{</span><br> <span class="hljs-keyword">semaphore_t</span> mutex; <span class="hljs-comment">// the mutex lock for going into the routines in monitor, should be initialized to 1</span><br> <span class="hljs-keyword">semaphore_t</span> next; <span class="hljs-comment">// the next semaphore is used to down the signaling proc itself, and the other OR wakeuped waiting proc should wake up the sleeped signaling proc.</span><br> <span class="hljs-keyword">int</span> next_count; <span class="hljs-comment">// the number of of sleeped signaling proc</span><br> <span class="hljs-keyword">condvar_t</span> *cv; <span class="hljs-comment">// the condvars in monitor</span><br>} <span class="hljs-keyword">monitor_t</span>;<br></code></pre></div></td></tr></tbody></table></figure><p>此处不再赘述,</p><p>在kern/sync/monitor.c,有monitor_init的实现:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> </span><br><span class="hljs-function"><span class="hljs-title">monitor_init</span> <span class="hljs-params">(<span class="hljs-keyword">monitor_t</span> * mtp, <span class="hljs-keyword">size_t</span> num_cv)</span> </span>{<br> <span class="hljs-keyword">int</span> i;<br> assert(num_cv><span class="hljs-number">0</span>);<br> mtp->next_count = <span class="hljs-number">0</span>;<br> mtp->cv = <span class="hljs-literal">NULL</span>;<br> <br> <span class="hljs-comment">//初始化锁为0,next为1</span><br> sem_init(&(mtp->mutex), <span class="hljs-number">1</span>); <span class="hljs-comment">//unlocked</span><br> sem_init(&(mtp->next), <span class="hljs-number">0</span>);<br> <span class="hljs-comment">//分配当前管程的条件变量</span><br> mtp->cv =(<span class="hljs-keyword">condvar_t</span> *) kmalloc(<span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">condvar_t</span>)*num_cv);<br> assert(mtp->cv!=<span class="hljs-literal">NULL</span>);<br> <span class="hljs-comment">//初始化管程</span><br> <span class="hljs-keyword">for</span>(i=<span class="hljs-number">0</span>; i<num_cv; i++){<br> mtp->cv[i].count=<span class="hljs-number">0</span>;<br> sem_init(&(mtp->cv[i].sem),<span class="hljs-number">0</span>);<br> mtp->cv[i].owner=mtp;<br> }<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>我们要实现的是接下来两个函数:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">// Unlock one of threads waiting on the condition variable. </span><br><span class="hljs-comment">//看注释知道要做什么</span><br><span class="hljs-function"><span class="hljs-keyword">void</span> </span><br><span class="hljs-function"><span class="hljs-title">cond_signal</span> <span class="hljs-params">(<span class="hljs-keyword">condvar_t</span> *cvp)</span> </span>{<br> <span class="hljs-comment">//LAB7 EXERCISE1: YOUR CODE</span><br> cprintf(<span class="hljs-string">"cond_signal begin: cvp %x, cvp->count %d, cvp->owner->next_count %d\n"</span>, cvp, cvp->count, cvp->owner->next_count); <br> <span class="hljs-comment">//打印提示信息</span><br> <span class="hljs-comment">//如果管程内等待的线程大于0个</span><br> <span class="hljs-keyword">if</span>(cvp->count><span class="hljs-number">0</span>) {<br> <span class="hljs-comment">//正在睡眠的进程++</span><br> cvp->owner->next_count ++;<br> <span class="hljs-comment">//尝试唤醒线程,更新信号量</span><br> up(&(cvp->sem));<br> <span class="hljs-comment">//正在执行的线程被挂起</span><br> down(&(cvp->owner->next));<br> <span class="hljs-comment">//睡眠线程就--</span><br> cvp->owner->next_count --;<br> }<br> <span class="hljs-comment">//打印提示信息</span><br> cprintf(<span class="hljs-string">"cond_signal end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n"</span>, cvp, cvp->count, cvp->owner->next_count);<br>}<br><br><span class="hljs-comment">// Suspend calling thread on a condition variable waiting for condition Atomically unlocks </span><br><span class="hljs-comment">// mutex and suspends calling thread on conditional variable after waking up locks mutex. Notice: mp is mutex semaphore for monitor's procedures</span><br><span class="hljs-function"><span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">cond_wait</span> <span class="hljs-params">(<span class="hljs-keyword">condvar_t</span> *cvp)</span> </span>{<br> <span class="hljs-comment">//LAB7 EXERCISE1: YOUR CODE</span><br> cprintf(<span class="hljs-string">"cond_wait begin: cvp %x, cvp->count %d, cvp->owner->next_count %d\n"</span>, cvp, cvp->count, cvp->owner->next_count);<br> <span class="hljs-comment">//打印信息</span><br> <span class="hljs-comment">//需要等待的线程++</span><br> cvp->count++;<br> <span class="hljs-comment">//如果有挂起的线程就线执行该线程</span><br> <span class="hljs-keyword">if</span>(cvp->owner->next_count > <span class="hljs-number">0</span>)<br> up(&(cvp->owner->next));<br> <span class="hljs-keyword">else</span><br> <span class="hljs-comment">//否则释放锁</span><br> up(&(cvp->owner->mutex));<br> <span class="hljs-comment">// 尝试获取条件变量 </span><br> down(&(cvp->sem));<br> <span class="hljs-comment">//需要等待的线程--</span><br> cvp->count --;<br> cprintf(<span class="hljs-string">"cond_wait end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n"</span>, cvp, cvp->count, cvp->owner->next_count);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>哲学家就餐问题基本和信号量的实现相同,此处不再赘述。</p><p>关于<code>能否不用基于信号量机制来完成条件变量?如果不能,请给出理由,如果能,请给出设计说明和具体实现。</code>,个人认为,条件变量实质上可以看作信号量的简陋版本。</p><p>如果分数低,可以按照网上的办法偷懒改grade.sh,也可以参考我之前写的办法。</p><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205281454978.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205281456958.png" srcset="/img/loading.gif" lazyload></p><h2 id="challenge1">challenge1</h2><blockquote><p>扩展练习 Challenge : 在ucore中实现简化的死锁和重入探测机制</p><p>在ucore下实现一种探测机制,能够在多进程/线程运行同步互斥问题时,动态判断当前系统是否出现了死锁产生的必要条件,是否产生了多个进程进入临界区的情况。如果发现,让系统进入monitor状态,打印出你的探测信息。</p></blockquote><h2 id="challengen2">challengen2</h2><blockquote><p>扩展练习 Challenge: 参考Linux的RCU机制,在ucore中实现简化的RCU机制</p><p>在ucore下实现下Linux的RCU同步互斥机制。可阅读相关Linux内核书籍或查询网上资料,可了解RCU的设计实现细节,然后简化实现在ucore中。要求有实验报告说明你的设计思路,并提供测试用例。下面是一些参考资料:</p><ul><li>http://www.ibm.com/developerworks/cn/linux/l-rcu/</li><li>http://www.diybl.com/course/6_system/linux/Linuxjs/20081117/151814.html</li></ul></blockquote><p>仍是源自<a href="https://github.com/PKUanonym/REKCARC-TSC-UHT/blob/master/%E5%A4%A7%E4%B8%89%E4%B8%8B/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/hw/2017/2014011330_738801_304307860_lab7-2014011330/lab7-challenge-2014011330.md">github</a></p><p>所谓RCU,实际上适用于多个读者,少的写者的情况。他甚至可以不对读者加锁,而只对写者加锁。这样满足了读者可以随时进行读取操作,减少开销,而写者则是正常的加锁策略。由此,需要解决的问题是,我在写共享资源的时候,有一个读者过来读,我怎么保证他读的对?写的进程会copy资源,并且移动资源到新的位置,在写的过程中,读者进程读取原先的位置,此时会报错。rcu通过“销毁不删除”来实现。即写进程写时默认删除原值,读者在写进程执行时读取则可以正常读到原先的值(此时不销毁),写进程结束后销毁原值,更改共享资源地址即可。</p><p>具体思路可以参考上述的github.</p><p>最终效果如下,由于没有实现相应的哲学家就餐问题,makegrade只有183,不过这不重要:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205281516855.png" srcset="/img/loading.gif" lazyload></p><p>由于只是简化实现,因此并没有对写者加锁的代码。代码解释:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">foo</span> {</span><br><span class="hljs-keyword">int</span> a;<br><span class="hljs-keyword">char</span> b;<br>} <span class="hljs-keyword">foo_t</span>;<br><br><span class="hljs-keyword">foo_t</span>* gbl_foo = <span class="hljs-literal">NULL</span>;<br><br><span class="hljs-keyword">foo_t</span>* old_foo_ref = <span class="hljs-literal">NULL</span>;<br><span class="hljs-keyword">foo_t</span>* new_foo_ref = <span class="hljs-literal">NULL</span>;<br><span class="hljs-keyword">int</span> grace_period_count = <span class="hljs-number">0</span>;<br><br><span class="hljs-keyword">semaphore_t</span> foo_sem;<br><span class="hljs-comment">//初始化</span><br><br><span class="hljs-comment">//信号量</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">rcu_read_lock</span><span class="hljs-params">(<span class="hljs-keyword">foo_t</span>* ref)</span> </span>{<br> <span class="hljs-keyword">bool</span> intr_flag;<br> local_intr_save(intr_flag);<br> {<br><span class="hljs-keyword">if</span> (ref == old_foo_ref) {<br>grace_period_count += <span class="hljs-number">1</span>;<br>}<br> }<br>}<br><span class="hljs-comment">//信号量</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">rcu_read_unlock</span><span class="hljs-params">(<span class="hljs-keyword">foo_t</span>* ref)</span> </span>{<br> <span class="hljs-keyword">bool</span> intr_flag;<br> local_intr_save(intr_flag);<br> {<br><span class="hljs-keyword">if</span> (ref == old_foo_ref) {<br>grace_period_count -= <span class="hljs-number">1</span>;<br>}<br> }<br>}<br><span class="hljs-comment">//重置</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">resync_rcu_trail</span><span class="hljs-params">()</span> </span>{<br><span class="hljs-keyword">return</span> (grace_period_count != <span class="hljs-number">0</span>);<br>}<br><span class="hljs-comment">//读,老进程就增加"宽限区"</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">foo_read</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{<br>cprintf(<span class="hljs-string">"Foo_read %d starts.\n"</span>, id);<br>rcu_read_lock(gbl_foo);<br><span class="hljs-comment">// 读取旧值的指针</span><br><span class="hljs-keyword">foo_t</span>* fp = gbl_foo;<br><span class="hljs-comment">// If fp == NULL, it means gbl_foo has been deleted (don't care whether it is destroyed)</span><br><span class="hljs-keyword">if</span> (fp != <span class="hljs-literal">NULL</span>) {<br><span class="hljs-comment">// Sleep for some time.</span><br> <span class="hljs-comment">//这里我不是很清楚为什么要sleep</span><br>do_sleep(<span class="hljs-number">2</span>);<br>cprintf(<span class="hljs-string">"[SAFE] foo_read: gbl_foo.a = %d, gbl_foo.b = %c\n"</span>, fp->a, fp->b);<br>} <span class="hljs-keyword">else</span> {<br>panic(<span class="hljs-string">"[DANGER] foo_read: attempt to read foo when foo is null."</span>);<br>}<br>rcu_read_unlock(fp);<br>cprintf(<span class="hljs-string">"Foo_read %d ends.\n"</span>, id);<br>}<br><span class="hljs-comment">//更新共享资源的位置,写</span><br><span class="hljs-comment">// Update the gbl_foo to new_fp and free the old_fp.</span><br><span class="hljs-comment">// However, the free process could happen when Line36 is running.</span><br><span class="hljs-comment">// Thus, we need to do the update but delay the destroy of old_foo.</span><br><span class="hljs-comment">// Until all foo_reads exits the critical area.</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">foo_update</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{<br>cprintf(<span class="hljs-string">"Foo_update %d starts.\n"</span>, id);<br><span class="hljs-comment">// foo_sem is a mutex for gbl_foo</span><br>down(&(foo_sem));<br><span class="hljs-keyword">foo_t</span>* old_fp = gbl_foo;<br>gbl_foo = new_foo_ref;<br>up(&(foo_sem));<br>cprintf(<span class="hljs-string">"Foo_update waiting for %d graceful period to finish.\n"</span>, grace_period_count);<br><span class="hljs-comment">// spin when process left in grace period</span><br><span class="hljs-keyword">while</span> (resync_rcu_trail()) schedule();<br>kfree(old_fp);<br>cprintf(<span class="hljs-string">"Foo_update %d ends.\n"</span>, id);<br>}<br><span class="hljs-comment">//测试rcu</span><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">check_rcu</span><span class="hljs-params">()</span> </span>{<br>sem_init(&(foo_sem), <span class="hljs-number">1</span>);<br>old_foo_ref = (<span class="hljs-keyword">foo_t</span>*) kmalloc(<span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">foo_t</span>));<br>old_foo_ref->a = <span class="hljs-number">5</span>;<br>old_foo_ref->b = <span class="hljs-string">'O'</span>;<br>new_foo_ref = (<span class="hljs-keyword">foo_t</span>*) kmalloc(<span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">foo_t</span>));<br>new_foo_ref->a = <span class="hljs-number">6</span>;<br>new_foo_ref->b = <span class="hljs-string">'N'</span>;<br><br>gbl_foo = old_foo_ref;<br><br><span class="hljs-keyword">int</span> r1k = kernel_thread(foo_read, (<span class="hljs-keyword">void</span> *)<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">int</span> r2k = kernel_thread(foo_read, (<span class="hljs-keyword">void</span> *)<span class="hljs-number">2</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">int</span> w1k = kernel_thread(foo_update, (<span class="hljs-keyword">void</span> *)<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">int</span> r3k = kernel_thread(foo_read, (<span class="hljs-keyword">void</span> *)<span class="hljs-number">3</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">int</span> r4k = kernel_thread(foo_read, (<span class="hljs-keyword">void</span> *)<span class="hljs-number">4</span>, <span class="hljs-number">0</span>);<br><br>do_wait(r1k, <span class="hljs-literal">NULL</span>);<br>do_wait(r2k, <span class="hljs-literal">NULL</span>);<br>do_wait(w1k, <span class="hljs-literal">NULL</span>);<br>do_wait(r3k, <span class="hljs-literal">NULL</span>);<br>do_wait(r4k, <span class="hljs-literal">NULL</span>);<br><br>cprintf(<span class="hljs-string">"check_rcu() passed\n"</span>);<br>}<br><br></code></pre></div></td></tr></tbody></table></figure>]]></content>
<summary type="html"><h1 id="练习解答">练习解答</h1>
<ul>
<li>理解操作系统的同步互斥的设计实现;</li>
<li>理解底层支撑技术:禁用中断、定时器、等待队列;</li>
<li>在ucore中理解信号量(semaphore)机制的具体实现;</li>
<li>理解管程机制</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>ucore-lab6</title>
<link href="https://heeler-deer.top/posts/44538/"/>
<id>https://heeler-deer.top/posts/44538/</id>
<published>2022-05-21T03:03:56.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="练习解答">练习解答</h1><h2 id="练习0">练习0</h2><p>填写实验</p><ul><li><p>kern/process/proc.c</p></li><li><p>kern/mm/pmm.c</p></li></ul><p>有需要更改的文件,建议看<a href="https://kiprey.github.io/2020/09/uCore-6/#%E7%BB%83%E4%B9%A0%E8%A7%A3%E7%AD%94">Kiprey</a></p><h2 id="练习1">练习1</h2><blockquote><p>练习1: 使用 Round Robin 调度算法(不需要编码)</p><p>完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件)个人完成的lab5和练习0完成后的刚修改的lab6之间的区别,分析了解lab6采用RR调度算法后的执行过程。执行makegrade,大部分测试用例应该通过。但执行priority.c应该过不去。</p><p>请在实验报告中完成:</p><ul><li>请理解并分析sched_class中各个函数指针的用法,并结合Round Robin调度算法描ucore的调度执行过程</li><li>请在实验报告中简要说明如何设计实现”多级反馈队列调度算法“,给出概要设计,鼓励给出详细设计</li></ul><p><strong>请理解并分析sched_class中各个函数指针的用法,并结合RoundRobin 调度算法描ucore的调度执行过程</strong></p></blockquote><p>在kern/schedule/sched.h不难找到:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sched_class</span> {</span><br> <span class="hljs-comment">// the name of sched_class</span><br> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *name;<br> <span class="hljs-comment">// Init the run queue</span><br> <span class="hljs-keyword">void</span> (*init)(struct run_queue *rq);<br> <span class="hljs-comment">// put the proc into runqueue, and this function must be called with rq_lock</span><br> <span class="hljs-keyword">void</span> (*enqueue)(struct run_queue *rq, struct proc_struct *proc);<br> <span class="hljs-comment">// get the proc out runqueue, and this function must be called with rq_lock</span><br> <span class="hljs-keyword">void</span> (*dequeue)(struct run_queue *rq, struct proc_struct *proc);<br> <span class="hljs-comment">// choose the next runnable task</span><br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *(*<span class="hljs-title">pick_next</span>)(<span class="hljs-keyword">struct</span> <span class="hljs-title">run_queue</span> *<span class="hljs-title">rq</span>);</span><br> <span class="hljs-comment">// dealer of the time-tick</span><br> <span class="hljs-keyword">void</span> (*proc_tick)(struct run_queue *rq, struct proc_struct *proc);<br> <span class="hljs-comment">/* for SMP support in the future</span><br><span class="hljs-comment"> * load_balance</span><br><span class="hljs-comment"> * void (*load_balance)(struct rq* rq);</span><br><span class="hljs-comment"> * get some proc from this rq, used in load_balance,</span><br><span class="hljs-comment"> * return value is the num of gotten proc</span><br><span class="hljs-comment"> * int (*get_proc)(struct rq* rq, struct proc* procs_moved[]);</span><br><span class="hljs-comment"> */</span><br>};<br></code></pre></div></td></tr></tbody></table></figure><p>由于时间较紧,且根据注释易于理解,此处不再赘述</p><p>在kern/schedule/default_sched.c不难找到rr算法的实现,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">RR_init</span><span class="hljs-params">(struct run_queue *rq)</span> </span>{<br> list_init(&(rq->run_list));<br> rq->proc_num = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-comment">//初始化对应的list</span><br><span class="hljs-comment">//run queue的进程号设置为0</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">RR_enqueue</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> assert(list_empty(&(proc->run_link)));<br> list_add_before(&(rq->run_list), &(proc->run_link));<br> <span class="hljs-keyword">if</span> (proc->time_slice == <span class="hljs-number">0</span> || proc->time_slice > rq->max_time_slice) {<br> <span class="hljs-comment">//进程时间片等于0或者大于最大时间片时,重新赋值</span><br> proc->time_slice = rq->max_time_slice;<br> }<br> proc->rq = rq;<br> rq->proc_num ++;<br>}<br><span class="hljs-comment">//将进程添加至队列,</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">RR_dequeue</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> assert(!list_empty(&(proc->run_link)) && proc->rq == rq);<br> list_del_init(&(proc->run_link));<br> rq->proc_num --;<br>}<br><span class="hljs-comment">//去除队列</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> struct proc_struct *</span><br><span class="hljs-function"><span class="hljs-title">RR_pick_next</span><span class="hljs-params">(struct run_queue *rq)</span> </span>{<br> <span class="hljs-keyword">list_entry_t</span> *le = list_next(&(rq->run_list));<br> <span class="hljs-keyword">if</span> (le != &(rq->run_list)) {<br> <span class="hljs-keyword">return</span> le2proc(le, run_link);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NULL</span>;<br>}<br><span class="hljs-comment">//选择队列最前面的进程</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">RR_proc_tick</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> <span class="hljs-keyword">if</span> (proc->time_slice > <span class="hljs-number">0</span>) {<br> proc->time_slice --;<br> }<br> <span class="hljs-keyword">if</span> (proc->time_slice == <span class="hljs-number">0</span>) {<br> proc->need_resched = <span class="hljs-number">1</span>;<br> }<br>}<br><span class="hljs-comment">//tick,用于时间片的处理,等于0是重新安排(resched)</span><br></code></pre></div></td></tr></tbody></table></figure><p>如注释所示。</p><p>那么也就是说,ucore的RR算法,首先调用kern/schedule/sched.c中的sched_init函数进行初始化(加入list),之后初始化进程(proc目录下的函数),ucore执行cpu_idle(proc目录下)函数,调用sched_class_enqueue加入队列,启动进程计时器。之后pick_next,有可以执行的进程就dequeue,继续proc_run.</p><p>相关调用图:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205211153269.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205211156860.png" srcset="/img/loading.gif" lazyload></p><p><strong>请在实验报告中简要说明如何设计实现”多级反馈队列调度算法“,给出概要设计,鼓励给出详细设计</strong></p><p>多级反馈队列实际上是通过设置多个优先级不同的队列实现,其中优先级越高,时间片越高。在enqueue中,如果该进程时间片为0则不改变其优先级,大于0则降低其优先级;调度时,参照ostep的规则,如果A 的优先级 > B 的优先级,运行 A(不运行 B);如果 A 的优先级 = B的优先级,轮转运行A 和B;新进程进入系统时,放在最高优先级(最上层队列);一旦工作用完了其在某一层中的时间配额(无论中间主动放弃了多少次CPU),就降低其优先级(移入低一级队列);经过一段时间S,就将系统中所有工作重新加入最高优先级队列。</p><h2 id="练习二">练习二</h2><blockquote><p>练习2: 实现 Stride Scheduling 调度算法(需要编码)</p><p>首先需要换掉RR调度器的实现,即用default_sched_stride_c覆盖default_sched.c。然后根据此文件和后续文档对Stride度器的相关描述,完成Stride调度算法的实现。</p><p>后面的实验文档部分给出了Stride调度算法的大体描述。这里给出Stride调度算法的一些相关的资料(目前网上中文的资料比较欠缺)。</p><ul><li><a href="http://wwwagss.informatik.uni-kl.de/Projekte/Squirrel/stride/node3.html">strid-shedpaper location1</a></li><li><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.138.3502&rank=1">strid-shedpaper location2</a></li><li>也可GOOGLE “Stride Scheduling” 来查找相关资料</li></ul><p>执行:makegrade。如果所显示的应用程序检测都输出ok,则基本正确。如果只是priority.c过不去,可执行make run-priority 命令来单独调试它。大致执行结果可看附录。( 使用的是qemu-1.0.1 )。</p><p>请在实验报告中简要说明你的设计实现过程。</p></blockquote><p>所谓stride算法,实际上就是通过对每一个进程添加一个stride以及一个pass数据,每次选择最小stride(或者说离cpu最近)的进程执行,执行后该进程的stride添加步长pass.其中pass与优先级成反比,pass=BIG_STRIDE/ priority</p><p>关于BIG_STRIDE的详细推导建议参考<a href="https://yuerer.com/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F-uCore-Lab-6/">yuerer</a></p><p>具体代码实现建议参考<a href="https://kiprey.github.io/2020/09/uCore-6/#2-%E7%BB%83%E4%B9%A02">kiprey</a></p><p>这里贴一下代码:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><defs.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><list.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><proc.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><assert.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><default_sched.h></span></span><br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> USE_SKEW_HEAP 1</span><br><br><span class="hljs-comment">/* You should define the BigStride constant here*/</span><br><span class="hljs-comment">/* LAB6: YOUR CODE */</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> BIG_STRIDE ((uint32_t) -1) / 2</span><br><span class="hljs-comment">//选取合适的进程</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span></span><br><span class="hljs-function"><span class="hljs-title">proc_stride_comp_f</span><span class="hljs-params">(<span class="hljs-keyword">void</span> *a, <span class="hljs-keyword">void</span> *b)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">p</span> =</span> le2proc(a, lab6_run_pool);<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">q</span> =</span> le2proc(b, lab6_run_pool);<br> <span class="hljs-keyword">int32_t</span> c = p->lab6_stride - q->lab6_stride;<br> <span class="hljs-keyword">if</span> (c > <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (c == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;<br>}<br><span class="hljs-comment">//直接选取斜堆的顶端,</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> struct proc_struct *</span><br><span class="hljs-function"><span class="hljs-title">stride_pick_next</span><span class="hljs-params">(struct run_queue *rq)</span> </span>{<br> <span class="hljs-keyword">skew_heap_entry_t</span>* she = rq->lab6_run_pool;<br> <span class="hljs-keyword">if</span> (she != <span class="hljs-literal">NULL</span>) {<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span>* <span class="hljs-title">p</span> =</span> le2proc(she, lab6_run_pool);<br> <span class="hljs-comment">//更新stride</span><br> p->lab6_stride += BIG_STRIDE / p->lab6_priority;<br> <span class="hljs-keyword">return</span> p;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NULL</span>;<br>}<br><br><span class="hljs-comment">//初始化,多了一个指针</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">stride_init</span><span class="hljs-params">(struct run_queue *rq)</span> </span>{<br> list_init(&(rq->run_list));<br> <br> rq->lab6_run_pool = <span class="hljs-literal">NULL</span>;<br> rq->proc_num = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-comment">//enqueue以及dequeue更新指针即可</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">stride_enqueue</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> rq->lab6_run_pool = skew_heap_insert(rq->lab6_run_pool, &(proc->lab6_run_pool), proc_stride_comp_f);<br> <span class="hljs-keyword">if</span> (proc->time_slice == <span class="hljs-number">0</span> || proc->time_slice > rq->max_time_slice) {<br> proc->time_slice = rq->max_time_slice;<br> }<br> proc->rq = rq;<br> rq->proc_num ++;<br>}<br><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">stride_dequeue</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> rq->lab6_run_pool = skew_heap_remove(rq->lab6_run_pool, &(proc->lab6_run_pool), proc_stride_comp_f);<br> rq->proc_num --;<br>}<br><span class="hljs-comment">//tick正常</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">stride_proc_tick</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> <span class="hljs-keyword">if</span> (proc->time_slice > <span class="hljs-number">0</span>) {<br> proc->time_slice --;<br> }<br> <span class="hljs-keyword">if</span> (proc->time_slice == <span class="hljs-number">0</span>) {<br> proc->need_resched = <span class="hljs-number">1</span>;<br> }<br>}<br><span class="hljs-comment">//改一下名字就好了</span><br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sched_class</span> <span class="hljs-title">default_sched_class</span> =</span> {<br> .name = <span class="hljs-string">"stride_scheduler"</span>,<br> .init = stride_init,<br> .enqueue = stride_enqueue,<br> .dequeue = stride_dequeue,<br> .pick_next = stride_pick_next,<br> .proc_tick = stride_proc_tick,<br>};<br><br></code></pre></div></td></tr></tbody></table></figure><p>到这里,执行make grade时,会出错。</p><p>根据网上博客,解决办法是注释掉grade.sh的221到233行,我们来看一下这一段:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash"> found和not相等就为真</span><br><span class="hljs-meta">#</span><span class="bash"> found,not都是标志变量,</span><br><span class="hljs-meta">#</span><span class="bash"> not在代码没有错误的情况下为0</span><br><span class="hljs-meta">#</span><span class="bash"> found=$(($? == <span class="hljs-number">0</span>)),不是很清楚在干什么。。。</span><br>if [ $found -eq $not ]; then<br> if [ $found -eq 0 ]; then<br> msg="!! error: missing '$i'"<br> else<br> msg="!! error: got unexpected line '$i'"<br> fi<br> okay=no<br> if [ -z "$error" ]; then<br> error="$msg"<br> else<br> error="$error\n$msg"<br> fi<br> fi<br></code></pre></div></td></tr></tbody></table></figure><p>这一段是在check_regexps里面,okay为no时就会报错,而ucore的最终得分就是通过检查有无报错产生的。如果想蒙混过关,把这个no改成yes或者注释掉这一段代码或者把-eq改成-ne就行了</p><p><del>但如果每一次验收实验都只是为了验收而验收,自己什么都没学到,那还有什么意思呢?</del></p><p><del>当然对os不感兴趣的话混就得了</del></p><p>实际上,我们的错误是由于一个细节,在之前的kern/schedule/default_sched.c中,优先级初始化为0,而0在stride中是不能作为被除数存在的,因此需要更改kern/process/proc.c中的proc->lab6_priority为1。</p><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205211518593.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205211518135.png" srcset="/img/loading.gif" lazyload></p><h2 id="challenge-1">Challenge 1</h2><p>扩展练习 Challenge 1 :实现 Linux 的 CFS 调度算法</p><p>在ucore的调度器框架下实现下Linux的CFS调度算法。可阅读相关Linux内核书籍或查询网上资料,可了解CFS的细节,然后大致实现在ucore中。</p><blockquote><p>CFS(完全公平调度器)实现的主要思想是维护为任务提供处理器时间方面的平衡(公平性)。它给每个进程设置了一个虚拟时钟vruntime。其中vruntime=实际运行时间∗1024/进程权重</p><p>进程按照各自不同的速率在物理时钟节拍内前进,优先级高则权重大,其虚拟时钟比真实时钟跑得慢,但获得比较多的运行时间;CFS调度器总是选择虚拟时钟跑得慢的进程来运行,从而让每个调度实体的虚拟运行时间互相追赶,进而实现进程调度上的平衡。</p><p>CFS使用<strong>红黑树</strong>来进行快速高效的插入和删除进程。</p></blockquote><p>仍是参考<a href="https://github.com/PKUanonym">PKUanonym</a>的仓库:<a href="https://github.com/PKUanonym/REKCARC-TSC-UHT/blob/master/%E5%A4%A7%E4%B8%89%E4%B8%8B/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/hw/2017/2014011330_738797_362804411_lab6-2014011330/lab6-challenge-2014011330.md">ucore</a></p><p>先上结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205211532686.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205211535426.png" srcset="/img/loading.gif" lazyload></p><p>下面分析佬的代码,</p><p>kern/schedule/cfs_sched.h没有什么大的改变,改个名字就好了</p><p>kern/schedule/cfs_sched.c中,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> NICE_0_LOAD 1024</span><br><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span></span><br><span class="hljs-function"><span class="hljs-title">proc_cfs_comp_f</span><span class="hljs-params">(<span class="hljs-keyword">void</span> *a, <span class="hljs-keyword">void</span> *b)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">p</span> =</span> le2proc(a, lab6_run_pool);<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">q</span> =</span> le2proc(b, lab6_run_pool);<br> <span class="hljs-keyword">int32_t</span> c = p->lab6_stride - q->lab6_stride;<br> <span class="hljs-keyword">if</span> (c > <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (c == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;<br>}<br><span class="hljs-comment">//绝对公平,不需要list或者其他数据</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">cfs_init</span><span class="hljs-params">(struct run_queue *rq)</span> </span>{<br>rq->lab6_run_pool = <span class="hljs-literal">NULL</span>;<br>rq->proc_num = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-comment">//enqueue以及dequeue没什么说的</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">cfs_enqueue</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br>rq->lab6_run_pool = skew_heap_insert(rq->lab6_run_pool, &(proc->lab6_run_pool),<br>proc_cfs_comp_f);<br> <span class="hljs-keyword">if</span> (proc->time_slice == <span class="hljs-number">0</span> || proc->time_slice > rq->max_time_slice) {<br> proc->time_slice = rq->max_time_slice;<br> }<br> proc->rq = rq;<br> rq->proc_num += <span class="hljs-number">1</span>;<br>}<br><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">cfs_dequeue</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br>rq->lab6_run_pool = skew_heap_remove(rq->lab6_run_pool, &(proc->lab6_run_pool),<br>proc_cfs_comp_f);<br>rq->proc_num -= <span class="hljs-number">1</span>;<br>}<br><span class="hljs-comment">//通过设置进程的时间来改变优先级,类似与stride</span><br><span class="hljs-comment">//可以对比一下,</span><br><span class="hljs-comment">/*</span><br><span class="hljs-comment">static struct proc_struct *</span><br><span class="hljs-comment">stride_pick_next(struct run_queue *rq) {</span><br><span class="hljs-comment"> skew_heap_entry_t* she = rq->lab6_run_pool;</span><br><span class="hljs-comment"> if (she != NULL) {</span><br><span class="hljs-comment"> struct proc_struct* p = le2proc(she, lab6_run_pool);</span><br><span class="hljs-comment"> //更新stride</span><br><span class="hljs-comment"> p->lab6_stride += BIG_STRIDE / p->lab6_priority;</span><br><span class="hljs-comment"> return p;</span><br><span class="hljs-comment"> }</span><br><span class="hljs-comment"> return NULL;</span><br><span class="hljs-comment">}</span><br><span class="hljs-comment">*/</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> struct proc_struct *</span><br><span class="hljs-function"><span class="hljs-title">cfs_pick_next</span><span class="hljs-params">(struct run_queue *rq)</span> </span>{<br><span class="hljs-keyword">if</span> (rq->lab6_run_pool == <span class="hljs-literal">NULL</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">NULL</span>;<br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span>* <span class="hljs-title">min_proc</span> =</span> le2proc(rq->lab6_run_pool, lab6_run_pool);<br><span class="hljs-keyword">if</span> (min_proc->lab6_priority == <span class="hljs-number">0</span>) {<br>min_proc->lab6_stride += NICE_0_LOAD;<br>} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (min_proc->lab6_priority > NICE_0_LOAD) {<br>min_proc->lab6_stride += <span class="hljs-number">1</span>;<br>} <span class="hljs-keyword">else</span> {<br>min_proc->lab6_stride += NICE_0_LOAD / min_proc->lab6_priority;<br>}<br><span class="hljs-keyword">return</span> min_proc;<br>}<br><span class="hljs-comment">//tick没什么</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">cfs_proc_tick</span><span class="hljs-params">(struct run_queue *rq, struct proc_struct *proc)</span> </span>{<br> <span class="hljs-keyword">if</span> (proc->time_slice > <span class="hljs-number">0</span>) {<br> proc->time_slice --;<br> }<br> <span class="hljs-keyword">if</span> (proc->time_slice == <span class="hljs-number">0</span>) {<br> proc->need_resched = <span class="hljs-number">1</span>;<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sched_class</span> <span class="hljs-title">cfs_sched_class</span> =</span> {<br> .name = <span class="hljs-string">"cfs_scheduler"</span>,<br> .init = cfs_init,<br> .enqueue = cfs_enqueue,<br> .dequeue = cfs_dequeue,<br> .pick_next = cfs_pick_next,<br> .proc_tick = cfs_proc_tick,<br>};<br><br></code></pre></div></td></tr></tbody></table></figure><h2 id="challenge-2">Challenge 2</h2><p>看着就知道工作量大,没空,也不会。</p><p>闲了再说。</p>]]></content>
<summary type="html"><h1 id="练习解答">练习解答</h1>
<h2 id="练习0">练习0</h2>
<p>填写实验</p>
<ul>
<li><p>kern/process/proc.c</p></li>
<li><p>kern/mm/pmm.c</p></li>
</ul>
<p>有需</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>ucore-lab5</title>
<link href="https://heeler-deer.top/posts/44218/"/>
<id>https://heeler-deer.top/posts/44218/</id>
<published>2022-05-13T08:24:25.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="练习解答">练习解答</h1><h2 id="实验目的">实验目的</h2><ul><li>了解第一个用户进程创建过程</li><li>了解系统调用框架的实现机制</li><li>了解ucore如何实现系统调用sys_fork/sys_exec/sys_exit/sys_wait来进行进程管理</li></ul><h2 id="实验内容">实验内容</h2><p>实验4完成了内核线程,但到目前为止,所有的运行都在内核态执行。实验5将<strong>创建用户进程</strong>,让用户进程在用户态执行,且在需要ucore支持时,可通过系统调用来让ucore提供服务。为此需要构造出第一个用户进程,并通过系统调用sys_fork/sys_exec/sys_exit/sys_wait来支持运行不同的应用程序,完成对用户进程的执行过程的基本管理。</p><h2 id="练习0填写已有实验">练习0:填写已有实验</h2><p>我的建议是照着result来完善代码。</p><p>这东西不能直接拿lab4做过的用,实在是败笔。</p><p>不嫌麻烦的可以参考<a href="https://kiprey.github.io/2020/08/uCore-5/">kiprey</a></p><h2 id="练习1加载应用程序并执行需要编码">练习1:加载应用程序并执行(需要编码)</h2><blockquote><p><strong>do_execv</strong>函数调用load_icode(位于kern/process/proc.c中)来加载并解析一个处于内存中的ELF执行文件格式的应用程序,建立相应的用户内存空间来放置应用程序的代码段、数据段等,且要设置好proc_struct结构中的成员变量trapframe中的内容,确保在执行此进程后,能够从应用程序设定的起始执行地址开始执行。需设置正确的trapframe内容。</p><p>请在实验报告中简要说明你的设计实现过程。</p><p>请在实验报告中描述当创建一个用户态进程并加载了应用程序后,CPU是如何让这个应用程序最终在用户态执行起来的。即这个用户态进程被ucore选择占用CPU执行(RUNNING态)到具体执行应用程序第一条指令的整个经过。</p></blockquote><p>代码:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">/* LAB5:EXERCISE1 YOUR CODE</span><br><span class="hljs-comment"> * should set tf_cs,tf_ds,tf_es,tf_ss,tf_esp,tf_eip,tf_eflags</span><br><span class="hljs-comment"> * NOTICE: If we set trapframe correctly, then the user level process can return to USER MODE from kernel. So</span><br><span class="hljs-comment"> * tf_cs should be USER_CS segment (see memlayout.h)</span><br><span class="hljs-comment"> * tf_ds=tf_es=tf_ss should be USER_DS segment</span><br><span class="hljs-comment"> * tf_esp should be the top addr of user stack (USTACKTOP)</span><br><span class="hljs-comment"> * tf_eip should be the entry point of this binary program (elf->e_entry)</span><br><span class="hljs-comment"> * tf_eflags should be set to enable computer to produce Interrupt</span><br><span class="hljs-comment"> */</span><br>tf->tf_cs = USER_CS;<br>tf->tf_ds = tf->tf_es = tf->tf_ss = USER_DS;<br>tf->tf_esp = USTACKTOP;<br>tf->tf_eip = elf->e_entry;<br>tf->tf_eflags = FL_IF;<br>ret = <span class="hljs-number">0</span>;<br></code></pre></div></td></tr></tbody></table></figure><p>读取文件需要陷入内核态,在load_icode中我们需要完成tf_cs,tf_ds,tf_es,tf_ss,tf_esp,tf_eip,tf_eflags这几个变量的初始化。这注释都已经把答案写出来了。<em><span class="github-emoji"><span>😆</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f606.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></em></p><p>实验让我们描述用户态进程从被选择执行到具体执行的经过。</p><p>建议参考<a href="https://www.cnblogs.com/wuhualong/p/ucore_lab5_report.html">博客园</a>,这里只给出部分关系图以及代码。</p><p>proc.c的cluster call internal:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205131715688.png" srcset="/img/loading.gif" lazyload></p><p>proc.c内部的流程大致如上,不难找到:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">related syscall <span class="hljs-keyword">for</span> process:<br>SYS_exit : process <span class="hljs-built_in">exit</span>, -->do_exit<br>SYS_fork : create child process, dup mm -->do_fork-->wakeup_proc<br>SYS_wait : wait process -->do_wait<br>SYS_exec : after fork, process execute a program -->load a program <span class="hljs-keyword">and</span> refresh the mm<br>SYS_clone : create child thread -->do_fork-->wakeup_proc<br>SYS_yield : process flag itself need resecheduling, -- proc->need_sched=<span class="hljs-number">1</span>, then scheduler will rescheule <span class="hljs-keyword">this</span> process<br>SYS_sleep : process sleep -->do_sleep <br>SYS_kill : kill process -->do_kill-->proc->flags |= PF_EXITING<br> -->wakeup_proc-->do_wait-->do_exit <br>SYS_getpid : get the process<span class="hljs-number">'</span>s pid<br></code></pre></div></td></tr></tbody></table></figure><h2 id="练习2-父进程复制自己的内存空间给子进程需要编码">练习2:父进程复制自己的内存空间给子进程(需要编码)</h2><blockquote><p>创建子进程的函数do_fork在执行中将拷贝当前进程(即父进程)的用户内存地址空间中的合法内容到新进程中(子进程),完成内存资源的复制。具体是通过copy_range函数(位于kern/mm/pmm.c中)实现的,请补充copy_range的实现,确保能够正确执行。</p><p>请在实验报告中简要说明如何设计实现”Copy on Write机制“,给出概要设计,鼓励给出详细设计。</p></blockquote><blockquote><p>Copy-on-write(简称COW)的基本概念是指如果有多个使用者对一个资源A(比如内存块)进行读操作,则每个使用者只需获得一个指向同一个资源A的指针,就可以该资源了。若某使用者需要对这个资源A进行写操作,系统会对该资源进行拷贝操作,从而使得该“写操作”使用者获得一个该资源A的“私有”拷贝—资源B,可对资源B进行写操作。该“写操作”使用者对资源B的改变对于其他的使用者而言是不可见的,因为其他使用者看到的还是资源A。</p></blockquote><p>代码:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"> <span class="hljs-comment">/* LAB5:EXERCISE2 YOUR CODE</span><br><span class="hljs-comment"> * replicate content of page to npage, build the map of phy addr of nage with the linear addr start</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Some Useful MACROs and DEFINEs, you can use them in below implementation.</span><br><span class="hljs-comment"> * MACROs or Functions:</span><br><span class="hljs-comment"> * page2kva(struct Page *page): return the kernel vritual addr of memory which page managed (SEE pmm.h)</span><br><span class="hljs-comment"> * page_insert: build the map of phy addr of an Page with the linear addr la</span><br><span class="hljs-comment"> * memcpy: typical memory copy function</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * (1) find src_kvaddr: the kernel virtual address of page</span><br><span class="hljs-comment"> * (2) find dst_kvaddr: the kernel virtual address of npage</span><br><span class="hljs-comment"> * (3) memory copy from src_kvaddr to dst_kvaddr, size is PGSIZE</span><br><span class="hljs-comment"> * (4) build the map of phy addr of nage with the linear addr start</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-keyword">void</span> * kva_src = page2kva(page);<br><span class="hljs-comment">//找到src页面所在地址</span><br> <span class="hljs-keyword">void</span> * kva_dst = page2kva(npage);<br><span class="hljs-comment">//找到dst页面所在地址</span><br> <span class="hljs-built_in">memcpy</span>(kva_dst, kva_src, PGSIZE);<br><span class="hljs-comment">//复制</span><br> ret = page_insert(to, npage, start, perm);<br><span class="hljs-comment">//按照链表方式加入pte</span><br> assert(ret == <span class="hljs-number">0</span>);<br> }<br> start += PGSIZE;<br></code></pre></div></td></tr></tbody></table></figure><h2 id="练习3-阅读分析源代码理解进程执行-forkexecwaitexit-的实现以及系统调用的实现不需要编码">练习3:阅读分析源代码,理解进程执行 fork/exec/wait/exit的实现,以及系统调用的实现(不需要编码)</h2><blockquote><p>请在实验报告中简要说明你对fork/exec/wait/exit函数的分析。并回答如下问题:</p><ul><li>请分析fork/exec/wait/exit在实现中是如何影响进程的执行状态的?</li><li>请给出ucore中一个用户态进程的执行状态生命周期图(包执行状态,执行状态之间的变换关系,以及产生变换的事件或函数调用)。(字符方式画即可)</li></ul><p>执行:makegrade。如果所显示的应用程序检测都输出ok,则基本正确。(使用的是qemu-1.0.1)</p></blockquote><p>注意,前面如果完全正确,参考我上周写的<a href="https://heeler-deer.github.io/2022/05/07/ucore-lab4/#%E7%BB%83%E4%B9%A02">lab4练习二</a>最后一部分更改一下语句就可以拿到136分。</p><p>之后参考<a href="https://www.cnblogs.com/wuhualong/p/ucore_lab5_report.html">博客园</a>且自己看提示信息,可以看出这东西确实有bug</p><p>我试了试,发现是init_main函数里面,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span></span><br><span class="hljs-function"><span class="hljs-title">init_main</span><span class="hljs-params">(<span class="hljs-keyword">void</span> *arg)</span> </span>{<br> <span class="hljs-comment">//注意此句</span><br> <span class="hljs-keyword">size_t</span> nr_free_pages_store = nr_free_pages();<br> <span class="hljs-keyword">size_t</span> kernel_allocated_store = kallocated();<br><br> <span class="hljs-keyword">int</span> pid = kernel_thread(user_main, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>);<br> <span class="hljs-keyword">if</span> (pid <= <span class="hljs-number">0</span>) {<br> panic(<span class="hljs-string">"create user_main failed.\n"</span>);<br> }<br> <span class="hljs-comment">//然而这里调用了do_wait,schedule,这两个函数调用了过多内存操作函数</span><br> <span class="hljs-comment">//具体我没有细看,但应该是这里出了问题</span><br> <span class="hljs-keyword">while</span> (do_wait(<span class="hljs-number">0</span>, <span class="hljs-literal">NULL</span>) == <span class="hljs-number">0</span>) {<br> schedule();<br> }<br><br> cprintf(<span class="hljs-string">"all user-mode processes have quit.\n"</span>);<br> assert(initproc->cptr == <span class="hljs-literal">NULL</span> && initproc->yptr == <span class="hljs-literal">NULL</span> && initproc->optr == <span class="hljs-literal">NULL</span>);<br> assert(nr_process == <span class="hljs-number">2</span>);<br> assert(list_next(&proc_list) == &(initproc->list_link));<br> assert(list_prev(&proc_list) == &(initproc->list_link));<br> <span class="hljs-comment">//此时不再相等,故删去assert</span><br> <span class="hljs-comment">//assert(nr_free_pages_store == nr_free_pages());</span><br> assert(kernel_allocated_store == kallocated());<br> cprintf(<span class="hljs-string">"init check memory pass.\n"</span>);<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>查看kern/mm/pmm.c中的nr_free_pages的函数调用图:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205132205375.png" srcset="/img/loading.gif" lazyload></p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">//nr_free_pages - call pmm->nr_free_pages to get the size (nr*PAGESIZE) </span><br><span class="hljs-comment">//of current free memory</span><br><span class="hljs-function"><span class="hljs-keyword">size_t</span></span><br><span class="hljs-function"><span class="hljs-title">nr_free_pages</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br> <span class="hljs-keyword">size_t</span> ret;<br> <span class="hljs-keyword">bool</span> intr_flag;<br> local_intr_save(intr_flag);<br> {<br> ret = pmm_manager->nr_free_pages();<br> }<br> local_intr_restore(intr_flag);<br> <span class="hljs-keyword">return</span> ret;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>在init_main注释这一句即可:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">//assert(nr_free_pages_store == nr_free_pages());</span><br></code></pre></div></td></tr></tbody></table></figure><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205132202628.png" srcset="/img/loading.gif" lazyload></p><ul><li>请分析fork/exec/wait/exit在实现中是如何影响进程的执行状态的?</li></ul><p>fork这些调用的都是sys内相应的函数,sys_fork这些又调用的syscall,syscall又调用的诸如do_fork一类。</p><p>do_fork之类函数过长,建议自己看</p><p>do_fork在练习四写过,这里粘贴一下:</p><p>在这个过程中,需要给新内核线程分配资源,并且复制原进程的状态。你需要完成在kern/process/proc.c中的do_fork函数中的处理过程。它的大致执行步骤包括:</p><ul><li>调用alloc_proc,首先获得一块用户信息块。</li><li>为进程分配一个内核栈。</li><li>复制原进程的内存管理信息到新进程(但内核线程不必做此事)</li><li>复制原进程上下文到新进程</li><li>将新进程添加到进程列表</li><li>唤醒新进程</li><li>返回新进程号</li></ul><p>do_exit以及do_wait直接引用<a href="https://www.cnblogs.com/wuhualong/p/ucore_lab5_report.html">博客园</a></p><blockquote><p>wait的实现</p></blockquote><blockquote><p>wait的功能是等待子进程结束,从而释放子进程占用的资源。在ucore中wait对应的函数是do_wait。</p><ol type="1"><li>遍历进程链表proc_list,根据输入参数寻找指定pid或任意pid的子进程,如果没找到,直接返回错误信息。</li><li>如果找到子进程,而且其状态为ZOMBIE,则释放子进程占用的资源,然后返回。</li><li>如果找到子进程,但状态不为ZOMBIE,则将当前进程的state设置为SLEEPING、wait_state设置为WT_CHILD,然后调用schedule函数,从而进入等待状态。等再次被唤醒后,重复寻找状态为ZOMBIE的子进程。</li></ol></blockquote><blockquote><p>exit的实现</p><p>exit的功能是释放进程占用的资源并结束运行进程。在ucore中exit对应的函数是do_exit。</p><ol type="1"><li>释放页表项记录的物理内存,以及mm结构、vma结构、页目录表占用的内存。</li><li>将自己的state设置为ZOMBIE,然后唤醒父进程,并调用schedule函数,等待父进程回收剩下的资源,最终彻底结束子进程。</li></ol></blockquote><ul><li>请给出ucore中一个用户态进程的执行状态生命周期图(包括执行状态,执行状态之间的变换关系,以及产生变换的事件或函数调用)。</li></ul><p>那就直接mermaid了,丑就丑吧 <span class="github-emoji"><span>🤐</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f910.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><pre><code class="mermaid" type="">flowchart TB ap([alloc_proc]) pi([proc_init]) ap-->pi r((ready_to_run)) pi-->r wu([wakeup_proc]) wu-->r d([调度器]) r-->d rr((running)) d-->rr dw([do_wait]) rr-->dw s((sleep)) dw-->s de([do_exit]) zz((ZOMBIE)) rr-->de de-->zz z((回收销毁)) de-->z d-->r rr-->d s-->wu</code></pre><h2 id="扩展练习-challenge-实现-copy-on-write-cow机制">扩展练习Challenge :实现 Copy on Write (COW)机制</h2><blockquote><p>给出实现源码,测试用例和设计报告(包括在cow情况下的各种状态转换(类似有限状态自动机)的说明)。</p><p>这个扩展练习涉及到本实验和上一个实验“虚拟内存管理”。在ucore操作系统中,当一个用户父进程创建自己的子进程时,父进程会把其申请的用户空间设置为只读,子进程可共享父进程占用的用户内存空间中的页面(这就是一个共享的资源)<strong>。当其中任何一个进程修改此用户内存空间中的某页面时,ucore会通过pagefault异常获知该操作,并完成拷贝内存页面</strong>,使得两个进程都有各自的内存页面。这样一个进程所做的修改不会被另外一个进程可见了。请在ucore中实现这样的COW机制。</p><p>由于COW实现比较复杂,容易引入bug,请参考 https://dirtycow.ninja/看看能否在ucore的COW实现中模拟这个错误和解决方案。需要有解释。</p><p>这是一个big challenge.</p></blockquote><p>不难理解是要干什么。</p><p>参考<a href="https://github.com/PKUanonym/REKCARC-TSC-UHT/blob/master/%E5%A4%A7%E4%B8%89%E4%B8%8B/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/hw/2017/2014011330_738795_163902674_lab5-2014011330/lab5-challenge-2014011330.md">github</a></p><p>我们要修改pmm.c中的copy_range以及处理页错误的page_fault函数:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">uint32_t</span> perm = (*ptep & (PTE_U | PTE_P));<br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">page</span> =</span> pte2page(*ptep);<br>assert(page != <span class="hljs-literal">NULL</span>);<br><span class="hljs-comment">// 令新页面对父进程只读</span><br>page_insert(to, page, start, perm);<br><span class="hljs-comment">// 旧页面只读</span><br>page_insert(from, page, start, perm);<br></code></pre></div></td></tr></tbody></table></figure><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">if</span> (*ptep & PTE_P) {<br><span class="hljs-comment">// Read-only possibly caused by COW.</span><br> <span class="hljs-comment">//确定可以写且可以更改</span><br><span class="hljs-keyword">if</span> (vma->vm_flags & VM_WRITE) {<br><span class="hljs-comment">// If ref of pages == 1, it is not shared, just make pte writable.</span><br><span class="hljs-comment">// else, alloc a new page, copy content and reset pte.</span><br><span class="hljs-comment">// also, remember to decrease ref of that page!</span><br> <span class="hljs-comment">//看佬的注释很容易明白</span><br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span>* <span class="hljs-title">p</span> =</span> pte2page(*ptep);<br>assert(p != <span class="hljs-literal">NULL</span>);<br>assert(p->ref > <span class="hljs-number">0</span>);<br><span class="hljs-keyword">if</span> (p->ref > <span class="hljs-number">1</span>) {<br> <span class="hljs-comment">//复制页面</span><br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">npage</span> =</span> alloc_page();<br>assert(npage != <span class="hljs-literal">NULL</span>);<br><span class="hljs-keyword">void</span> * src_kvaddr = page2kva(p);<br><span class="hljs-keyword">void</span> * dst_kvaddr = page2kva(npage);<br><span class="hljs-built_in">memcpy</span>(dst_kvaddr, src_kvaddr, PGSIZE);<br><span class="hljs-comment">// addr already ROUND down.</span><br> <span class="hljs-comment">//插入</span><br>page_insert(mm->pgdir, npage, addr, ((*ptep) & PTE_USER) | PTE_W);<br><span class="hljs-comment">// page_ref_dec(p);</span><br> <span class="hljs-comment">//</span><br>cprintf(<span class="hljs-string">"Handled one COW fault at %x: copied\n"</span>, addr);<br>} <span class="hljs-keyword">else</span> {<br>page_insert(mm->pgdir, p, addr, ((*ptep) & PTE_USER) | PTE_W);<br>cprintf(<span class="hljs-string">"Handled one COW fault: reused\n"</span>);<br>}<br>} <span class="hljs-keyword">else</span> {<br>cprintf(<span class="hljs-string">"Not a COW read-only fault.\n"</span>);<br><span class="hljs-keyword">goto</span> failed;<br>}<br>} <span class="hljs-keyword">else</span> {<br><span class="hljs-comment">// 处理缺页</span><br>}<br></code></pre></div></td></tr></tbody></table></figure><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205132248605.png" srcset="/img/loading.gif" lazyload></p><p>由于一些原因,我并没有按照佬的md做出来Handled one COW fault:reused,所以就鸽了。。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205132303683.png" srcset="/img/loading.gif" lazyload></p>]]></content>
<summary type="html"><h1 id="练习解答">练习解答</h1>
<h2 id="实验目的">实验目的</h2>
<ul>
<li>了解第一个用户进程创建过程</li>
<li>了解系统调用框架的实现机制</li>
<li>了解ucore如何实现系统调用sys_fork/sys_exec/sys_</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>ucore-lab4</title>
<link href="https://heeler-deer.top/posts/27771/"/>
<id>https://heeler-deer.top/posts/27771/</id>
<published>2022-05-07T05:45:11.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="知识点">知识点</h1><p>由于本人在操作系统精髓与设计原理中学习过这一部分,故略</p><h1 id="练习解答">练习解答</h1><h2 id="实验目的">实验目的</h2><ul><li>了解内核线程创建/执行的管理过程</li><li>了解内核线程的切换和基本调度过程</li></ul><p>内核线程是一种特殊的进程,内核线程与用户进程的区别有两个:</p><ul><li>内核线程只运行在内核态</li><li>用户进程会在在用户态和内核态交替运行</li><li>所有内核线程共用ucore内核内存空间,不需为每个内核线程维护单独的内存空间</li><li>而用户进程需要维护各自的用户内存空间</li></ul><h2 id="练习0">练习0</h2><p>填写已有实验</p><p>meld合并即可。</p><p>kern/mm/vmm.c</p><h2 id="练习1">练习1</h2><h4 id="分配并初始化一个进程控制块需要编码">分配并初始化一个进程控制块(需要编码)</h4><p>alloc_proc函数(位于kern/process/proc.c中)负责分配并返回一个新的structproc_struct结构,用于存储新建立的内核线程的管理信息。ucore需要对这个结构进行最基本的初始化,你需要完成这个初始化过程。</p><blockquote><p>【提示】在alloc_proc函数的实现中,需要初始化的proc_struct结构中的成员变量至少包括:state/pid/runs/kstack/need_resched/parent/mm/context/tf/cr3/flags/name。</p></blockquote><p>请在实验报告中简要说明你的设计实现过程。请回答如下问题:</p><ul><li>请说明proc_struct中<code>struct context context</code>和<code>struct trapframe *tf</code>成员变量含义和在本实验中的作用是啥?(提示通过看代码和编程调试可以判断出来)</li></ul><p>这东西就照着注释写就行,没意思。</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> struct proc_struct *</span><br><span class="hljs-function"><span class="hljs-title">alloc_proc</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">proc</span> =</span> kmalloc(<span class="hljs-keyword">sizeof</span>(struct proc_struct));<br> <span class="hljs-keyword">if</span> (proc != <span class="hljs-literal">NULL</span>) {<br> <span class="hljs-comment">//LAB4:EXERCISE1 YOUR CODE</span><br> <span class="hljs-comment">/*</span><br><span class="hljs-comment"> * below fields in proc_struct need to be initialized</span><br><span class="hljs-comment"> * enum proc_state state; // Process state</span><br><span class="hljs-comment"> * int pid; // Process ID</span><br><span class="hljs-comment"> * int runs; // the running times of Proces</span><br><span class="hljs-comment"> * uintptr_t kstack; // Process kernel stack</span><br><span class="hljs-comment"> * volatile bool need_resched; // bool value: need to be rescheduled to release CPU?</span><br><span class="hljs-comment"> * struct proc_struct *parent; // the parent process</span><br><span class="hljs-comment"> * struct mm_struct *mm; // Process's memory management field</span><br><span class="hljs-comment"> * struct context context; // Switch here to run process</span><br><span class="hljs-comment"> * struct trapframe *tf; // Trap frame for current interrupt</span><br><span class="hljs-comment"> * uintptr_t cr3; // CR3 register: the base addr of Page Directroy Table(PDT)</span><br><span class="hljs-comment"> * uint32_t flags; // Process flag</span><br><span class="hljs-comment"> * char name[PROC_NAME_LEN + 1]; // Process name</span><br><span class="hljs-comment"> */</span><br> proc->state = PROC_UNINIT;<br> proc->pid = <span class="hljs-number">-1</span>;<br> proc->runs = <span class="hljs-number">0</span>;<br> proc->kstack = <span class="hljs-number">0</span>;<br> proc->need_resched = <span class="hljs-number">0</span>;<br> proc->parent = <span class="hljs-literal">NULL</span>;<br> proc->mm = <span class="hljs-literal">NULL</span>;<br> <span class="hljs-built_in">memset</span>(&(proc->context), <span class="hljs-number">0</span>, <span class="hljs-keyword">sizeof</span>(struct context));<br> proc->tf = <span class="hljs-literal">NULL</span>;<br> proc->cr3 = boot_cr3;<br> proc->flags = <span class="hljs-number">0</span>;<br> <span class="hljs-built_in">memset</span>(proc->name, <span class="hljs-number">0</span>, PROC_NAME_LEN);<br> }<br> <span class="hljs-keyword">return</span> proc;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>不难想到context是上下文的那个context,trapframe应该是陷阱相关代码。</p><p>我们看一下proc.c的butterfly图。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071710465.png" srcset="/img/loading.gif" lazyload></p><p>在看一下proc.c的内部调用图。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071711729.png" srcset="/img/loading.gif" lazyload></p><p>在proc.h中不难找到:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">context</span> {</span><br> <span class="hljs-keyword">uint32_t</span> eip;<br> <span class="hljs-keyword">uint32_t</span> esp;<br> <span class="hljs-keyword">uint32_t</span> ebx;<br> <span class="hljs-keyword">uint32_t</span> ecx;<br> <span class="hljs-keyword">uint32_t</span> edx;<br> <span class="hljs-keyword">uint32_t</span> esi;<br> <span class="hljs-keyword">uint32_t</span> edi;<br> <span class="hljs-keyword">uint32_t</span> ebp;<br>};<br></code></pre></div></td></tr></tbody></table></figure><p>容易发现,context中存储的是进程/线程切换上下文所需要的'寄存器',不管对于内核态还是用户态都要用到这几个寄存器.</p><p>学习过csapp的人应该对这几个名字都很熟悉了,不再介绍了。</p><p>在trap.h中不难找到:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">trapframe</span> {</span><br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">pushregs</span> <span class="hljs-title">tf_regs</span>;</span><br> <span class="hljs-keyword">uint16_t</span> tf_gs;<br> <span class="hljs-keyword">uint16_t</span> tf_padding0;<br> <span class="hljs-keyword">uint16_t</span> tf_fs;<br> <span class="hljs-keyword">uint16_t</span> tf_padding1;<br> <span class="hljs-keyword">uint16_t</span> tf_es;<br> <span class="hljs-keyword">uint16_t</span> tf_padding2;<br> <span class="hljs-keyword">uint16_t</span> tf_ds;<br> <span class="hljs-keyword">uint16_t</span> tf_padding3;<br> <span class="hljs-keyword">uint32_t</span> tf_trapno;<br> <span class="hljs-comment">/* below here defined by x86 hardware */</span><br> <span class="hljs-keyword">uint32_t</span> tf_err;<br> <span class="hljs-keyword">uintptr_t</span> tf_eip;<br> <span class="hljs-keyword">uint16_t</span> tf_cs;<br> <span class="hljs-keyword">uint16_t</span> tf_padding4;<br> <span class="hljs-keyword">uint32_t</span> tf_eflags;<br> <span class="hljs-comment">/* below here only when crossing rings, such as from user to kernel */</span><br> <span class="hljs-keyword">uintptr_t</span> tf_esp;<br> <span class="hljs-keyword">uint16_t</span> tf_ss;<br> <span class="hljs-keyword">uint16_t</span> tf_padding5;<br>} __attribute__((packed));<br></code></pre></div></td></tr></tbody></table></figure><p>显然,trap是用户态转为内核态时所作的操作,上述代码按照名字猜测,cs/ss/ds以及另外三个都是段寄存器的名称,该结构体应该是定义了从内核态切换到用户态所需要的数据。</p><p>我们着重看一下pro.c中的copy_thread函数来理解两者的作用。</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">copy_thread</span><span class="hljs-params">(struct proc_struct *proc, <span class="hljs-keyword">uintptr_t</span> esp, struct trapframe *tf)</span> </span>{<br> proc->tf = (struct trapframe *)(proc->kstack + KSTACKSIZE) - <span class="hljs-number">1</span>;<br> *(proc->tf) = *tf;<br> proc->tf->tf_regs.reg_eax = <span class="hljs-number">0</span>;<br> proc->tf->tf_esp = esp;<br> proc->tf->tf_eflags |= FL_IF;<br><br> proc->context.eip = (<span class="hljs-keyword">uintptr_t</span>)forkret;<br> proc->context.esp = (<span class="hljs-keyword">uintptr_t</span>)(proc->tf);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>在内核态切换到用户态的过程中,该函数不仅使用了context切换上下文,还使用了tf去切换到用户态。这两者似乎有重复。</p><p>然而实际上,通过context代码可以看出来,所谓的上下文切换,只是单纯的切换了寄存器数据,并没有更改内核态为用户态,仅用context切换数据的进程还处于原先的状态,context里面的eip寄存器,用来存储CPU要读取指令的地址,而esp只有设置为tf,才能执行用户代码。</p><h2 id="练习2">练习2</h2><h4 id="练习2为新创建的内核线程分配资源需要编码">练习2:为新创建的内核线程分配资源(需要编码)</h4><p>创建一个内核线程需要分配和设置好很多资源。kernel_thread函数通过调用<strong>do_fork</strong>函数完成具体内核线程的创建工作。do_kernel函数会调用alloc_proc函数来分配并初始化一个进程控制块,但alloc_proc只是找到了一小块内存用以记录进程的必要信息,并没有实际分配这些资源。ucore一般通过do_fork实际创建新的内核线程。do_fork的作用是,创建当前内核线程的一个副本,它们的执行上下文、代码、数据都一样,但是存储位置不同。在这个过程中,需要给新内核线程分配资源,并且复制原进程的状态。你需要完成在kern/process/proc.c中的do_fork函数中的处理过程。它的大致执行步骤包括:</p><ul><li>调用alloc_proc,首先获得一块用户信息块。</li><li>为进程分配一个内核栈。</li><li>复制原进程的内存管理信息到新进程(但内核线程不必做此事)</li><li>复制原进程上下文到新进程</li><li>将新进程添加到进程列表</li><li>唤醒新进程</li><li>返回新进程号</li></ul><p>请在实验报告中简要说明你的设计实现过程。请回答如下问题:</p><ul><li>请说明ucore是否做到给每个新fork的线程一个唯一的id?请说明你的分析和理由。</li></ul><p>注意该句:</p><blockquote><p>do_fork的作用是,创建当前内核线程的一个副本,它们的执行上下文、代码、数据都一样,但是存储位置不同。</p></blockquote><p>显然,我们需要注意<code>上下文、代码、数据</code></p><p>do_fork:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">// 分配一个PCB</span><br><span class="hljs-keyword">if</span> ((proc = alloc_proc()) == <span class="hljs-literal">NULL</span>)<br> <span class="hljs-keyword">goto</span> fork_out;<br><span class="hljs-comment">// 设置子进程的父进程</span><br>proc->parent = current;<br><span class="hljs-comment">// 分配内核栈</span><br><span class="hljs-keyword">if</span> (setup_kstack(proc) != <span class="hljs-number">0</span>)<br> <span class="hljs-keyword">goto</span> bad_fork_cleanup_proc;<br><span class="hljs-comment">// 复制内存数据--数据</span><br><span class="hljs-keyword">if</span> (copy_mm(clone_flags, proc) != <span class="hljs-number">0</span>)<br> <span class="hljs-keyword">goto</span> bad_fork_cleanup_kstack;<br><span class="hljs-comment">// 用刚刚讲过的copy_thread--上下文</span><br>copy_thread(proc, <span class="hljs-built_in">stack</span>, tf);<br><span class="hljs-comment">// 将子进程的PCB添加进hash表,让内核认识pcb</span><br><span class="hljs-keyword">bool</span> intr_flag;<br>local_intr_save(intr_flag);<br>{<br> proc->pid = get_pid();<br> hash_proc(proc);<br> list_add(&proc_list, &(proc->list_link));<br> nr_process ++;<br>}<br>local_intr_restore(intr_flag);<br><span class="hljs-comment">// 设置新的子进程可执行</span><br>wakeup_proc(proc);<br><span class="hljs-comment">// 返回子进程的pid</span><br>ret = proc->pid;<br></code></pre></div></td></tr></tbody></table></figure><p>ucore是否做到给每个新fork的线程一个唯一的id?显然,既然需要加入hash表,那么一定可以唯一的标识一个线程,查看get_pid函数可知,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span></span><br><span class="hljs-function"><span class="hljs-title">get_pid</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br> <span class="hljs-comment">//确认pid大于进程数量</span><br> <span class="hljs-keyword">static_assert</span>(MAX_PID > MAX_PROCESS);<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">proc</span>;</span><br> <span class="hljs-keyword">list_entry_t</span> *<span class="hljs-built_in">list</span> = &proc_list, *le;<br> <span class="hljs-comment">//注意是static,储存在静态存储空间而非栈</span><br> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> next_safe = MAX_PID, last_pid = MAX_PID;<br> <span class="hljs-comment">//last_pid大于max_pid的话,设置last_pid=1</span><br> <span class="hljs-comment">//即跳转到inside,重新设置next_safe</span><br> <span class="hljs-keyword">if</span> (++ last_pid >= MAX_PID) {<br> last_pid = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">goto</span> inside;<br> }<br> <span class="hljs-comment">//last_pid>next_safe,</span><br> <span class="hljs-keyword">if</span> (last_pid >= next_safe) {<br> inside:<br> next_safe = MAX_PID;<br> repeat:<br> le = <span class="hljs-built_in">list</span>;<br> <span class="hljs-comment">//分配唯一的pid</span><br> <span class="hljs-keyword">while</span> ((le = list_next(le)) != <span class="hljs-built_in">list</span>) {<br> <span class="hljs-comment">//在proc_list构建结构体</span><br> proc = le2proc(le, list_link);<br> <span class="hljs-comment">//两者pid相等的话</span><br> <span class="hljs-keyword">if</span> (proc->pid == last_pid) {<br> <span class="hljs-comment">//last_pid>=next_safe|max_pid就重置</span><br> <span class="hljs-keyword">if</span> (++ last_pid >= next_safe) {<br> <span class="hljs-keyword">if</span> (last_pid >= MAX_PID) {<br> last_pid = <span class="hljs-number">1</span>;<br> }<br> next_safe = MAX_PID;<br> <span class="hljs-keyword">goto</span> repeat;<br> }<br> }<br> <span class="hljs-comment">//不等且</span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (proc->pid > last_pid && next_safe > proc->pid) {<br> <span class="hljs-comment">//以proc的pid构建next_safe</span><br> next_safe = proc->pid;<br> }<br> }<br> }<br> <span class="hljs-keyword">return</span> last_pid;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>上述代码实际上是构建了一个next_safe,last_pid的区间。通过确认没有进程的id在则这个区间内部,来分配一个合适的pid。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071711146.png" srcset="/img/loading.gif" lazyload></p><p>通过移动last_pid(+1,重置时置1),移动proc->pid(已有进程的pid),以及next_safe(等于max_pid,分配成功时置为proc->pid)</p><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071711309.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071711574.png" srcset="/img/loading.gif" lazyload></p><p>需要注意的是,这个grade.sh有点问题,需要修改kern/mm/kmalloc.c的代码为:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">check_slab</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br> cprintf(<span class="hljs-string">"check_slab() succeeded!\n"</span>);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>才可以100分。应该是设计评分系统时与之前输出语句不同,因此会造成上图的error</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071712799.png" srcset="/img/loading.gif" lazyload></p><h2 id="练习3">练习3</h2><p>阅读代码,理解 proc_run函数和它调用的函数如何完成进程切换的。(无编码工作)</p><p>请在实验报告中简要说明你对proc_run函数的分析。并回答如下问题:</p><ul><li>在本实验的执行过程中,创建且运行了几个内核线程?</li><li>语句<code>local_intr_save(intr_flag);....local_intr_restore(intr_flag);</code>在这里有何作用?请说明理由</li></ul><p>proc_run:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">proc_run</span><span class="hljs-params">(struct proc_struct *proc)</span> </span>{<br> <span class="hljs-keyword">if</span> (proc != current) {<br> <span class="hljs-keyword">bool</span> intr_flag;<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">proc_struct</span> *<span class="hljs-title">prev</span> =</span> current, *next = proc;<br> local_intr_save(intr_flag);<br> {<br> <span class="hljs-comment">// 设置当前执行的进程</span><br> current = proc;<br> <span class="hljs-comment">// 设置ring0的内核栈地址</span><br> load_esp0(next->kstack + KSTACKSIZE);<br> <span class="hljs-comment">// 加载页目录表</span><br> lcr3(next->cr3);<br> <span class="hljs-comment">// 切换上下文</span><br> switch_to(&(prev->context), &(next->context));<br> }<br> local_intr_restore(intr_flag);<br> }<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>butterfly图:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205071712796.png" srcset="/img/loading.gif" lazyload></p><p>涉及到的函数及注释:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">bool</span><br>__intr_save(<span class="hljs-keyword">void</span>) {<br> <span class="hljs-comment">//读取flag,关闭中断</span><br> <span class="hljs-keyword">if</span> (read_eflags() & FL_IF) {<br> intr_disable();<br> <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><br><span class="hljs-comment">/* *</span><br><span class="hljs-comment"> * load_esp0 - change the ESP0 in default task state segment,</span><br><span class="hljs-comment"> * so that we can use different kernel stack when we trap frame</span><br><span class="hljs-comment"> * user to kernel.</span><br><span class="hljs-comment"> * */</span><br><span class="hljs-comment">//加载内核栈基地址</span><br><span class="hljs-function"><span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">load_esp0</span><span class="hljs-params">(<span class="hljs-keyword">uintptr_t</span> esp0)</span> </span>{<br> ts.ts_esp0 = esp0;<br>}<br><br><span class="hljs-comment">//cr3页寄存器改为页目录表</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">lcr3</span><span class="hljs-params">(<span class="hljs-keyword">uintptr_t</span> cr3)</span> </span>{<br> <span class="hljs-function"><span class="hljs-keyword">asm</span> <span class="hljs-title">volatile</span> <span class="hljs-params">(<span class="hljs-string">"mov %0, %%cr3"</span> :: <span class="hljs-string">"r"</span> (cr3) : <span class="hljs-string">"memory"</span>)</span></span>;<br>}<br><br><span class="hljs-comment">//允许中断</span><br><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">void</span><br>__intr_restore(<span class="hljs-keyword">bool</span> flag) {<br> <span class="hljs-keyword">if</span> (flag) {<br> intr_enable();<br> }<br>}<br><br><br><br><span class="hljs-comment">//kern/process/switch.S</span><br>.text<br>.globl switch_to<br>switch_to: # switch_to(from, to)<br><br> <span class="hljs-meta"># save from<span class="hljs-meta-string">'s registers</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl 4(%esp), %eax # eax points to from</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> popl 0(%eax) # save eip !popl</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> #从这里开始保存寄存器到context</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %esp, 4(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %ebx, 8(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %ecx, 12(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %edx, 16(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %esi, 20(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %edi, 24(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> movl %ebp, 28(%eax)</span></span><br><span class="hljs-meta-string"><span class="hljs-meta"></span></span><br><span class="hljs-meta-string"><span class="hljs-meta"> # restore to'</span>s registers</span><br> #从这里开始恢复context<br> movl <span class="hljs-number">4</span>(%esp), %eax <span class="hljs-meta"># not 8(%esp): popped return address already</span><br> <span class="hljs-meta"># eax now points to to</span><br> movl <span class="hljs-number">28</span>(%eax), %ebp<br> movl <span class="hljs-number">24</span>(%eax), %edi<br> movl <span class="hljs-number">20</span>(%eax), %esi<br> movl <span class="hljs-number">16</span>(%eax), %edx<br> movl <span class="hljs-number">12</span>(%eax), %ecx<br> movl <span class="hljs-number">8</span>(%eax), %ebx<br> movl <span class="hljs-number">4</span>(%eax), %esp<br><br> pushl <span class="hljs-number">0</span>(%eax) <span class="hljs-meta"># push eip</span><br><br> ret<br></code></pre></div></td></tr></tbody></table></figure><ul><li>在本实验的执行过程中,创建且运行了几个内核线程?</li></ul><p>两个内核线程,分别是<code>idleproc</code>和<code>initproc</code></p><p>首先是idleproc内核线程,该线程是最初的内核线程,完成内核中各个子线程的创建以及初始化。之后循环执行调度,执行其他进程。还有一个是initproc内核线程,该线程主要是为了显示实验的完成而打印出字符串"helloworld"的内核线程。</p><p>语句<code>local_intr_save(intr_flag);....local_intr_restore(intr_flag);</code>在这里有何作用?请说明理由</p><p>见上文</p><h2 id="challenge">challenge</h2><p>实现支持任意大小的内存分配算法</p><p>这不是本实验的内容,其实是上一次实验内存的扩展,但考虑到现在的slab算法比较复杂,有必要实现一个比较简单的任意大小内存分配算法。可参考本实验中的slab如何调用基于页的内存分配算法(注意,不是要你关注slab的具体实现)来实现first-fit/best-fit/worst-fit/buddy等支持任意大小的内存分配算法。</p><p>由first-fit更改为best-fit代码参考<a href="https://github.com/PKUanonym/REKCARC-TSC-UHT/blob/master/%E5%A4%A7%E4%B8%89%E4%B8%8B/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/hw/2017/2014011330_738793_537703740_lab4-2014011330/kern/mm/kmalloc.c">github</a></p><p>核心代码为:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> *<span class="hljs-title">best_fit_alloc</span><span class="hljs-params">(<span class="hljs-keyword">size_t</span> size, <span class="hljs-keyword">gfp_t</span> gfp, <span class="hljs-keyword">int</span> align)</span></span><br><span class="hljs-function"></span>{<br>assert( (size + SLOB_UNIT) < PAGE_SIZE );<br><span class="hljs-comment">// This best fit allocator does not consider situations where align != 0</span><br> <span class="hljs-comment">//确认align==0</span><br>assert(align == <span class="hljs-number">0</span>);<br> <span class="hljs-comment">//slob大小</span><br><span class="hljs-keyword">int</span> units = SLOB_UNITS(size);<br><br><span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">long</span> flags;<br>spin_lock_irqsave(&slob_lock, flags);<br><br><span class="hljs-keyword">slob_t</span> *prev = slobfree, *cur = slobfree->next;<br><span class="hljs-keyword">int</span> find_available = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">int</span> best_frag_units = <span class="hljs-number">100000</span>;<br><span class="hljs-keyword">slob_t</span> *best_slob = <span class="hljs-literal">NULL</span>;<br><span class="hljs-keyword">slob_t</span> *best_slob_prev = <span class="hljs-literal">NULL</span>;<br> <span class="hljs-comment">//循环找到符合条件的单元</span><br><span class="hljs-keyword">for</span> (; ; prev = cur, cur = cur->next) {<br><span class="hljs-keyword">if</span> (cur->units >= units) {<br><span class="hljs-comment">// Find available one.</span><br><span class="hljs-keyword">if</span> (cur->units == units) {<br><span class="hljs-comment">// If found a perfect one...</span><br>prev->next = cur->next;<br>slobfree = prev;<br>spin_unlock_irqrestore(&slob_lock, flags);<br><span class="hljs-comment">// That's it!</span><br><span class="hljs-keyword">return</span> cur;<br>}<br><span class="hljs-keyword">else</span> {<br><span class="hljs-comment">// This is not a prefect one.</span><br> <span class="hljs-comment">//如果不能完美的放进去,就更改你的best大小</span><br><span class="hljs-keyword">if</span> (cur->units - units < best_frag_units) {<br><span class="hljs-comment">// This seems to be better than previous one.</span><br>best_frag_units = cur->units - units;<br>best_slob = cur;<br>best_slob_prev = prev;<br>find_available = <span class="hljs-number">1</span>;<br>}<br>}<br><br>}<br><br><span class="hljs-comment">// Get to the end of iteration.</span><br> <span class="hljs-comment">//符合条件就分配</span><br><span class="hljs-keyword">if</span> (cur == slobfree) {<br><span class="hljs-keyword">if</span> (find_available) {<br><span class="hljs-comment">// use the found best fit.</span><br>best_slob_prev->next = best_slob + units;<br>best_slob_prev->next->units = best_frag_units;<br>best_slob_prev->next->next = best_slob->next;<br>best_slob->units = units;<br>slobfree = best_slob_prev;<br>spin_unlock_irqrestore(&slob_lock, flags);<br><span class="hljs-comment">// That's it!</span><br><span class="hljs-keyword">return</span> best_slob;<br>}<br><span class="hljs-comment">// Initially, there's no available arena. So get some.</span><br>spin_unlock_irqrestore(&slob_lock, flags);<br><span class="hljs-keyword">if</span> (size == PAGE_SIZE) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br><br>cur = (<span class="hljs-keyword">slob_t</span> *)__slob_get_free_page(gfp);<br><span class="hljs-keyword">if</span> (!cur) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br><br>slob_free(cur, PAGE_SIZE);<br>spin_lock_irqsave(&slob_lock, flags);<br>cur = slobfree;<br>}<br>}<br>}<br></code></pre></div></td></tr></tbody></table></figure>]]></content>
<summary type="html"><h1 id="知识点">知识点</h1>
<p>由于本人在操作系统精髓与设计原理中学习过这一部分,故略</p>
<h1 id="练习解答">练习解答</h1>
<h2 id="实验目的">实验目的</h2>
<ul>
<li>了解内核线程创建/执行的管理过程</li>
<li></summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>ucore-lab3</title>
<link href="https://heeler-deer.top/posts/44602/"/>
<id>https://heeler-deer.top/posts/44602/</id>
<published>2022-04-28T02:49:31.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<p>本实验主要是对页替换算法的实现</p><p>woc,有人写了<a href="https://1790865014.gitbook.io/ucore-step-by-step/">ucorestep-by-step</a>,太强了。</p><h1 id="知识点">知识点</h1><p>当程序访问内存时,会出现三种情况:</p><ul><li>写入一个存在物理页的虚拟页</li><li>读一个不存在的页</li><li>不满足访问权限</li></ul><p>这时就需要缺页处理程序来处理,cpu会把产生异常的线性地址存储到lab2里提到过的cr2寄存器中,并且把页访问异常的错误码存放在中断栈中。</p><p>这里只讨论物理页面不够用的时候,应该置换那个物理页面。</p><p>需要注意的是,置换页面的选择仅限于当前进程占用的物理页面。</p><p>常见的页面置换算法包括课上提到的LRU,近似LRU,在lab3的资料中提到的clock类似于近似LRU。这些置换算法都是局部置换算法。</p><p>假如使用全局置换算法,即为进程分配大小可变的物理页面,就需要解决不同的问题:</p><ul><li>进程的内存需求的变换</li><li>分配给进程的物理页面数</li></ul><p>常见的算法有<code>工作集置换算法</code>,通过维护一个固定时间内进程访问的页面(工作集),在访问时换出不在工作集的页面、缺页时换入页面,同时更新访存链表来实现。</p><p>另一个算法是缺页率置换算法(PPF),即通过调节常驻集(当前时刻进程实际驻留在内存中的页面集合)的大小来使每一个进程的缺页率保持在一个合理范围内。</p><p>上述的局部置换算法以及全局置换算法都可能出现分配物理页面数增加而缺页率上升的异常情况,<strong>这被叫做belady</strong>现象。</p><h1 id="练习">练习</h1><p><sub>不知道你们怎么知道可以make_grade的</sub></p><h2 id="练习0">练习0</h2><p>用meld合并即可</p><p>修改的文件:</p><ul><li>kern/mm/default_pmm.c</li><li>kern/mm/pmm.c</li></ul><h2 id="练习1">练习1</h2><p>完成do_pgfault(kern/mm/vmm.c)函数,给未被映射的地址映射上物理页。</p><p>该段代码上方有call graph:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">CALL GRAPH: trap--> trap_dispatch-->pgfault_handler-->do_pgfault<br></code></pre></div></td></tr></tbody></table></figure><p><del>不得不说,vsc的那个tabnine aiassitant是挂,我还没写完就直接显示出ai分析的代码了,写if的时候直接分析出我想写的代码,纯纯的挂。</del></p><p>exercise1代码:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">/*LAB3 EXERCISE 1: YOUR CODE*/</span><br><span class="hljs-comment">//(1) try to find a pte, if pte's PT(Page Table) isn't existed, then create a PT.</span><br><span class="hljs-keyword">if</span>((ptep=get_pte(mm->pgdir,addr,<span class="hljs-number">1</span>))==<span class="hljs-literal">NULL</span>){<br> cprintf(<span class="hljs-string">"get_pte in do_pgfault failed\n"</span>);<br> <span class="hljs-keyword">goto</span> failed;<br>}<br><span class="hljs-keyword">if</span> (*ptep == <span class="hljs-number">0</span>) {<br><span class="hljs-comment">//(2) if the phy addr isn't exist, then alloc a page & map the phy addr with logical addr</span><br><span class="hljs-keyword">if</span>(pgdir_alloc_page(mm->pgdir,addr,perm)== <span class="hljs-literal">NULL</span>){<br> cprintf(<span class="hljs-string">"pgdir_alloc_page in do_pgfault failed\n"</span>);<br> <span class="hljs-keyword">goto</span> failed;<br>}<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>主要思路就是先查找当前虚拟地址对应的页表项,判断对应的*ptep是不是等于0(不存在),如果不存在就分配一块物理页。</p><p>make qemu前记得make clean</p><p>结果:</p><p>由于实在很难截图,所以这是在练习二完成后截的图</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204301032929.png" srcset="/img/loading.gif" lazyload></p><ul><li>请描述页目录项(Page Directory Entry)和页表项(Page TableEntry)中组成部分对ucore实现页替换算法的潜在用处。</li></ul><p>参考<a href="https://heeler-deer.github.io/2022/04/21/ucore-lab2/#%E7%BB%83%E4%B9%A0%E4%BA%8C">hd</a></p><ul><li>如果ucore的缺页服务例程在执行过程中访问内存,出现了页访问异常,请问硬件要做哪些事情?</li></ul><p>套娃了属于是</p><ol type="1"><li>将发生错误的虚拟地址保存在lab2提到过的cr2寄存器中</li><li>压入EFLAGS,CS,EIP,错误码和中断号至当前的内核栈中</li><li>保存上下文并执行新的缺页中断程序,之后回复上下文</li><li>继续执行当前的缺页处理</li></ol><h2 id="练习2">练习2</h2><p>还是在kern/mm/vmm.c里面,不难发现要完成else选项,即物理页面存在的情况;还要完成kern/mm/swap_fifo.c,实现基于fifo的页面替换算法。</p><p>kern/mm/vmm.c代码如下:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"> <span class="hljs-keyword">else</span> { <span class="hljs-comment">// if this pte is a swap entry, then load data from disk to a page with phy addr</span><br> <span class="hljs-comment">// and call page_insert to map the phy addr with logical addr</span><br> <span class="hljs-keyword">if</span>(swap_init_ok) {<br> struct Page *page=<span class="hljs-literal">NULL</span>;<br> <span class="hljs-keyword">if</span> ((ret = swap_in(mm, addr, &page)) != <span class="hljs-number">0</span>) {<br> cprintf(<span class="hljs-string">"swap_in in do_pgfault failed\n"</span>);<br> <span class="hljs-keyword">goto</span> failed;<br> } <br> page_insert(mm->pgdir, page, addr, perm);<br> swap_map_swappable(mm, addr, page, <span class="hljs-number">1</span>);<br> page->pra_vaddr = addr;<br> }<br> <span class="hljs-keyword">else</span> {<br> cprintf(<span class="hljs-string">"no swap_init_ok but ptep is %x, failed\n"</span>,*ptep);<br> <span class="hljs-keyword">goto</span> failed;<br> }<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>else代表这个页表项的物理页存在但不在内存中,首先判断是否swap空间初始化完成,如果完成则可以将数据加载到新的在内存的物理页中,将新的物理页与虚拟地址关联,同时将请求的物理页设置为可以swap,即可以被替换。</p><p>kern/mm/swap_fifo.c的代码:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">/*LAB3 EXERCISE 2: YOUR CODE*/</span> <br>list_add(head, entry);<br></code></pre></div></td></tr></tbody></table></figure><p>只需要加入list的首部即可。</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">//(1) unlink the earliest arrival page in front of pra_list_head qeueue</span><br><span class="hljs-comment">//(2) assign the value of *ptr_page to the addr of this page </span><br><span class="hljs-keyword">list_entry_t</span> *le = head->prev;<br>assert(head!=le);<br><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">p</span> =</span> le2page(le, pra_page_link);<br>list_del(le);<br>assert(p !=<span class="hljs-literal">NULL</span>);<br>*ptr_page = p;<br></code></pre></div></td></tr></tbody></table></figure><p>把list的首个节点删除的操作,学过数据结构应该都熟悉。</p><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204301050148.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204301125606.png" srcset="/img/loading.gif" lazyload></p><ul><li>如果要在ucore上实现"extendedclock页替换算法"请给你的设计方案,现有的swap_manager框架是否足以支持在ucore中实现此算法?如果是,请给你的设计方案。如果不是,请给出你的新的扩展和基此扩展的设计方案。并需要回答如下问题<ul><li>需要被换出的页的特征是什么?</li><li>在ucore中如何判断具有这样特征的页?</li><li>何时进行换入和换出操作?</li></ul></li></ul><p>首先是可以支持的,那么需要被换出的页的特征应该就是PTE_P以及PTE_D均为0的页,也就是换出不存在于内存中且未被其他进程修改的物理页。</p><p>其次,根据页结构,显然可以通过位运算查看PTE_P以及PTE_D.</p><p>最后,缺页时可以换入,物理页满时换出。根据 <span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.113ex" height="2.009ex" role="img" focusable="false" viewBox="0 -683 3144 888"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43E" d="M285 628Q285 635 228 637Q205 637 198 638T191 647Q191 649 193 661Q199 681 203 682Q205 683 214 683H219Q260 681 355 681Q389 681 418 681T463 682T483 682Q500 682 500 674Q500 669 497 660Q496 658 496 654T495 648T493 644T490 641T486 639T479 638T470 637T456 637Q416 636 405 634T387 623L306 305Q307 305 490 449T678 597Q692 611 692 620Q692 635 667 637Q651 637 651 648Q651 650 654 662T659 677Q662 682 676 682Q680 682 711 681T791 680Q814 680 839 681T869 682Q889 682 889 672Q889 650 881 642Q878 637 862 637Q787 632 726 586Q710 576 656 534T556 455L509 418L518 396Q527 374 546 329T581 244Q656 67 661 61Q663 59 666 57Q680 47 717 46H738Q744 38 744 37T741 19Q737 6 731 0H720Q680 3 625 3Q503 3 488 0H478Q472 6 472 9T474 27Q478 40 480 43T491 46H494Q544 46 544 71Q544 75 517 141T485 216L427 354L359 301L291 248L268 155Q245 63 245 58Q245 51 253 49T303 46H334Q340 37 340 35Q340 19 333 5Q328 0 317 0Q314 0 280 1T180 2Q118 2 85 2T49 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Z"></path></g><g data-mml-node="mi" transform="translate(889,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1234,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z"></path></g><g data-mml-node="mi" transform="translate(1737,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mi" transform="translate(2203,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2654,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g></g></g></svg></mjx-container></span>的说法,要注意对脏页的处理,</p><blockquote><p>可以在修改dirty的时候写入外存,或者可以在最终要删除该物理页时再写入外存。后者有利于多个写操作的合并,降低缺页代价,但此时的页替换算法却退化成普通的clock算法,而不是extendedclock算法了。</p></blockquote><h2 id="challenge1">challenge1</h2><p>实现识别dirty bit的 extended clock页替换算法(需要编程)</p><blockquote><ul><li>改进的时钟(EnhancedClock)页替换算法:在时钟置换算法中,淘汰一个页面时只考虑了页面是否被访问过,但在实际情况中,还应考虑被淘汰的页面是否被修改过。因为淘汰修改过的页面还需要写回硬盘,使得其置换代价大于未修改过的页面,所以优先淘汰没有修改的页,减少磁盘操作次数。改进的时钟置换算法除了考虑页面的访问情况,还需考虑页面的修改情况。即该算法不但希望淘汰的页面是最近未使用的页,而且还希望被淘汰的页是在主存驻留期间其页面内容未被修改过的。这需要为每一页的对应页表项内容中增加一位引用位和一位修改位。当该页被访问时,CPU中的MMU硬件将把访问位置“1”。当该页被“写”时,CPU中的MMU硬件将把修改位置“1”。这样这两位就存在四种可能的组合情况:(0,0)表示最近未被引用也未被修改,首先选择此页淘汰;(0,1)最近未被使用,但被修改,其次选择;(1,0)最近使用而未修改,再次选择;(1,1)最近使用且修改,最后选择。该算法与时钟算法相比,可进一步减少磁盘的I/O操作次数,但为了查找到一个尽可能适合淘汰的页面,可能需要经过多次扫描,增加了算法本身的执行开销。</li></ul></blockquote><p>更改swap_out_victim函数即可。</p><p>思路如下:</p><ul><li>第一次查找有没有0,0的页,有就换出,同时更改PTE_A为0,重置TLB缓存</li><li>第二次查找有没有0,0的页,有就换出,同时更改PTE_D为0,重置TLB缓存</li><li>第三次遍历链表必定存在0,0的页,换出即可。</li></ul><p>代码及注释:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span><br>_fifo_swap_out_victim(struct mm_struct *mm, struct Page ** ptr_page, <span class="hljs-keyword">int</span> in_tick)<br>{<br> <span class="hljs-keyword">list_entry_t</span> *head=(<span class="hljs-keyword">list_entry_t</span>*) mm->sm_priv;<br> assert(head != <span class="hljs-literal">NULL</span>);<br> assert(in_tick==<span class="hljs-number">0</span>);<br> <span class="hljs-comment">/* Select the victim */</span><br> <span class="hljs-comment">/*LAB3 EXERCISE 2: YOUR CODE*/</span> <br> <span class="hljs-comment">//(1) unlink the earliest arrival page in front of pra_list_head qeueue</span><br> <span class="hljs-comment">//(2) assign the value of *ptr_page to the addr of this page</span><br> <span class="hljs-comment">/* Select the tail */</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i<<span class="hljs-number">3</span>;i++){<br> <span class="hljs-comment">//三次遍历</span><br> <span class="hljs-keyword">list_entry_t</span> *le=head->prev;<br> assert(head!=le);<br> <span class="hljs-keyword">while</span>(le!=head){<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">p</span>=</span>le2page(le,pra_page_link);<br> <span class="hljs-keyword">pte_t</span>* ptep=get_pte(mm->pgdir,p->pra_vaddr,<span class="hljs-number">0</span>);<br> <span class="hljs-keyword">if</span>(!(*ptep & PTE_A)&& !(*ptep&PTE_D)){<br> <span class="hljs-comment">//看是不是0,0</span><br> list_del(le);<br> assert(p!=<span class="hljs-literal">NULL</span>);<br> *ptr_page=p;<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br><br> }<br> <span class="hljs-keyword">if</span>(i==<span class="hljs-number">0</span>)*ptep &= ~PTE_A;<br> <span class="hljs-comment">//第一次查找重置PTE_A</span><br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i==<span class="hljs-number">1</span>)*ptep &= ~PTE_D;<br> <span class="hljs-comment">//第二次查找重置PTE_D</span><br> le =le->prev;<br> tlb_invalidate(mm->pgdir,le);<br> <br> }<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204301113424.png" srcset="/img/loading.gif" lazyload></p><h2 id="challenge2没做出来">challenge2没做出来</h2><p><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.113ex" height="2.009ex" role="img" focusable="false" viewBox="0 -683 3144 888"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43E" d="M285 628Q285 635 228 637Q205 637 198 638T191 647Q191 649 193 661Q199 681 203 682Q205 683 214 683H219Q260 681 355 681Q389 681 418 681T463 682T483 682Q500 682 500 674Q500 669 497 660Q496 658 496 654T495 648T493 644T490 641T486 639T479 638T470 637T456 637Q416 636 405 634T387 623L306 305Q307 305 490 449T678 597Q692 611 692 620Q692 635 667 637Q651 637 651 648Q651 650 654 662T659 677Q662 682 676 682Q680 682 711 681T791 680Q814 680 839 681T869 682Q889 682 889 672Q889 650 881 642Q878 637 862 637Q787 632 726 586Q710 576 656 534T556 455L509 418L518 396Q527 374 546 329T581 244Q656 67 661 61Q663 59 666 57Q680 47 717 46H738Q744 38 744 37T741 19Q737 6 731 0H720Q680 3 625 3Q503 3 488 0H478Q472 6 472 9T474 27Q478 40 480 43T491 46H494Q544 46 544 71Q544 75 517 141T485 216L427 354L359 301L291 248L268 155Q245 63 245 58Q245 51 253 49T303 46H334Q340 37 340 35Q340 19 333 5Q328 0 317 0Q314 0 280 1T180 2Q118 2 85 2T49 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Z"></path></g><g data-mml-node="mi" transform="translate(889,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1234,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z"></path></g><g data-mml-node="mi" transform="translate(1737,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mi" transform="translate(2203,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2654,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g></g></g></svg></mjx-container></span>学长留坑了,我<del>也不想做了</del>打算做一做。</p><p>实现不考虑实现开销和效率的LRU页替换算法(需要编程)</p><p>既然不考虑开销和效率,那就简单多了,近似LRU都不需要,直接遍历链表。</p>]]></content>
<summary type="html"><p>本实验主要是对页替换算法的实现</p>
<p>woc,有人写了<a href="https://1790865014.gitbook.io/ucore-step-by-step/">ucore
step-by-step</a>,太强了。</p>
<h1 id="知识点">知</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>ucore-lab2</title>
<link href="https://heeler-deer.top/posts/28411/"/>
<id>https://heeler-deer.top/posts/28411/</id>
<published>2022-04-21T11:40:54.000Z</published>
<updated>2023-08-29T07:44:46.024Z</updated>
<content type="html"><![CDATA[<h1 id="参考资料">参考资料</h1><p><a href="https://github.com/ZebornDuan/UCore/blob/master/lab2/buddy.md">ZebornDuan</a></p><p><a href="https://kiprey.github.io/2020/08/uCore-2/">Kiprey</a></p><h1 id="知识点">知识点</h1><h2 id="连续内存分配">连续内存分配</h2><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204212010076.png" srcset="/img/loading.gif" lazyload></p><p>最先匹配就是寻找第一个大于所需空间的空闲块。</p><p>最佳匹配找到比n大的最小的那个空闲块,可以减少碎片的尺度。</p><p>最差匹配找不小于n的最大空闲分区。可以避免出现太多小碎片,但外部碎片较多,释放慢。</p><p>非连续式内存就是常见的段表管理机制。</p><p>其他内容建议看<a href="https://kiprey.github.io/2020/08/uCore-2/#1-%E7%9F%A5%E8%AF%86%E7%82%B9">Kiprey</a></p><h1 id="ucore_lab2">ucore_lab2</h1><h2 id="练习0">练习0</h2><p>合并代码,直接meld然后copy to right就行,lab1修改的文件有:</p><ul><li>kern/debug/kdebug.c</li><li>kern/trap/trap.c</li><li>kern/init/init.c</li></ul><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232059210.png" srcset="/img/loading.gif" lazyload></p><p>可以看到lab2与lab1有很多文件不同,记得只能修改上述三个文件。</p><h2 id="练习1">练习1</h2><p>找到kern/mm/default_pmm.c,按照提示分别查看default_init,default_init_memmap,default_alloc_pages,default_free_pages等相关函数。</p><p>首先看 <strong>default_init_memmap</strong>函数,这个函数要实现的是对内存块的初始化,通过传入页基址以及大小来插入页,但在最下面一行可以看到:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">list_add(&free_list, &(base->page_link));<br></code></pre></div></td></tr></tbody></table></figure><p>list_add是什么?</p><p>可以看到注释:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">* First, you should get familiar with the <span class="hljs-class"><span class="hljs-keyword">struct</span> `<span class="hljs-title">list</span>` <span class="hljs-title">in</span> <span class="hljs-title">list</span>.<span class="hljs-title">h</span>. <span class="hljs-title">Struct</span></span><br><span class="hljs-class">* `<span class="hljs-title">list</span>` <span class="hljs-title">is</span> <span class="hljs-title">a</span> <span class="hljs-title">simple</span> <span class="hljs-title">doubly</span> <span class="hljs-title">linked</span> <span class="hljs-title">list</span> <span class="hljs-title">implementation</span>. <span class="hljs-title">You</span> <span class="hljs-title">should</span> <span class="hljs-title">know</span> <span class="hljs-title">how</span> <span class="hljs-title">to</span></span><br><span class="hljs-class">* <span class="hljs-title">USE</span> `<span class="hljs-title">list_init</span>`, `<span class="hljs-title">list_add</span>`(`<span class="hljs-title">list_add_after</span>`), `<span class="hljs-title">list_add_before</span>`, `<span class="hljs-title">list_del</span>`,</span><br><span class="hljs-class">* `<span class="hljs-title">list_next</span>`, `<span class="hljs-title">list_prev</span>`.</span><br></code></pre></div></td></tr></tbody></table></figure><p>这就有问题了。之前讲过,first-fit算法是寻找第一个满足内存需求的地址空间,通过一个链表来实现这个功能。但list_add函数是把元素加在listelm的后面,只有list_add_before函数是把元素加在listelm的前面,因此我们应该使用list_add_before。具体list实现位于libs/list.h,</p><p>list_add:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">/* *</span><br><span class="hljs-comment"> * list_add - add a new entry</span><br><span class="hljs-comment"> * @listelm: list head to add after</span><br><span class="hljs-comment"> * @elm: new entry to be added</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Insert the new element @elm *after* the element @listelm which</span><br><span class="hljs-comment"> * is already in the list.</span><br><span class="hljs-comment"> * */</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">list_add</span><span class="hljs-params">(<span class="hljs-keyword">list_entry_t</span> *listelm, <span class="hljs-keyword">list_entry_t</span> *elm)</span> </span>{<br> list_add_after(listelm, elm);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>list_add_before:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-comment">/* *</span><br><span class="hljs-comment"> * list_add_before - add a new entry</span><br><span class="hljs-comment"> * @listelm: list head to add before</span><br><span class="hljs-comment"> * @elm: new entry to be added</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Insert the new element @elm *before* the element @listelm which</span><br><span class="hljs-comment"> * is already in the list.</span><br><span class="hljs-comment"> * */</span><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">list_add_before</span><span class="hljs-params">(<span class="hljs-keyword">list_entry_t</span> *listelm, <span class="hljs-keyword">list_entry_t</span> *elm)</span> </span>{<br> __list_add(elm, listelm->prev, listelm);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>因此可以更改为:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">list_add_before(&free_list, &(base->page_link));<br></code></pre></div></td></tr></tbody></table></figure><p>接着看 <strong>default_alloc_pages</strong>函数,看名字猜测应该是用于分配空间的函数。仔细看一下他的实现,不难发现,程序在分配完空间后仍旧按照原先的顺序排列链表中分配剩余的内存元素,因此我们要更改代码为:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">if</span> (page != <span class="hljs-literal">NULL</span>) {<br> <span class="hljs-keyword">if</span> (page->property > n) {<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">p</span> =</span> page + n;<br> p->property = page->property - n;<br> <span class="hljs-comment">//减掉分配的空间</span><br> SetPageProperty(p);<br> <span class="hljs-comment">//重新设置页属性</span><br> list_add_after(&(page->page_link), &(p->page_link));<br> <span class="hljs-comment">//加入链表</span><br> }<br> list_del(&(page->page_link));<br> <span class="hljs-comment">//删掉原先链表中的节点</span><br> nr_free -= n;<br> ClearPageProperty(page);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>而原先的代码是:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">if</span> (page != <span class="hljs-literal">NULL</span>) {<br> list_del(&(page->page_link));<br> <span class="hljs-keyword">if</span> (page->property > n) {<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">p</span> =</span> page + n;<br> p->property = page->property - n;<br> <span class="hljs-comment">//减掉分配的空间</span><br> list_add(&free_list, &(p->page_link));<br> <span class="hljs-comment">//直接add了</span><br> }<br> nr_free -= n;<br> ClearPageProperty(page);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>最后看 <strong>default_free_pages</strong>函数,用于释放页。考虑first-fit算法,在释放页的时候应该按照大小顺序插入链表,但该函数里面仍采用了list_add函数,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span></span><br><span class="hljs-function"><span class="hljs-title">default_free_pages</span><span class="hljs-params">(struct Page *base, <span class="hljs-keyword">size_t</span> n)</span> </span>{<br> assert(n > <span class="hljs-number">0</span>);<br> <span class="hljs-comment">//确认空闲空间大于0</span><br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">p</span> =</span> base;<br> <span class="hljs-keyword">for</span> (; p != base + n; p ++) {<br> assert(!PageReserved(p) && !PageProperty(p));<br> p->flags = <span class="hljs-number">0</span>;<br> set_page_ref(p, <span class="hljs-number">0</span>);<br> }<br> base->property = n;<br> <span class="hljs-comment">//页的大小设置为n</span><br> SetPageProperty(base);<br> <span class="hljs-keyword">list_entry_t</span> *le = list_next(&free_list);<br> <span class="hljs-keyword">while</span> (le != &free_list) {<br> p = le2page(le, page_link);<br> le = list_next(le);<br> <span class="hljs-keyword">if</span> (base + base->property == p) {<br> base->property += p->property;<br> ClearPageProperty(p);<br> list_del(&(p->page_link));<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (p + p->property == base) {<br> p->property += base->property;<br> ClearPageProperty(base);<br> base = p;<br> list_del(&(p->page_link));<br> }<br> }<br> <span class="hljs-comment">//循环找到空闲空间的地址并合并</span><br> nr_free += n;<br> list_add(&free_list, &(base->page_link));<br> <span class="hljs-comment">//此处直接list_add,显然不对</span><br>}<br></code></pre></div></td></tr></tbody></table></figure><p>那么我们就需要把最后一句代码修改为:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-keyword">for</span>(le = list_next(&free_list); le != &free_list; le = list_next(le))<br>{<br> p = le2page(le, page_link);<br> <span class="hljs-keyword">if</span> (base + base->property <= p) {<br> assert(base + base->property != p);<br> <span class="hljs-keyword">break</span>;<br> }<br>}<br><span class="hljs-comment">//循环找到大于le的空间的第一个节点,插入到其前面</span><br>list_add_before(le, &(base->page_link));<br></code></pre></div></td></tr></tbody></table></figure><p>first-fit算法是通过采用链表来实现查找的,实际上可以采用更高效的数据结构比如bst,红黑树这些。</p><p>执行 <code>make qemu</code> 得到:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232059073.png" srcset="/img/loading.gif" lazyload></p><p>小字部分显示 <code>check_alloc_page() succeeded!</code> 即为成功</p><h2 id="练习二">练习二</h2><p>补全get_pte函数,该函数的call graph如下:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232059948.png" srcset="/img/loading.gif" lazyload></p><p>在kern/mm/pmm.c找到get_pte函数,根据注释不难写出:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">pte_t</span> *</span><br><span class="hljs-function"><span class="hljs-title">get_pte</span><span class="hljs-params">(<span class="hljs-keyword">pde_t</span> *pgdir, <span class="hljs-keyword">uintptr_t</span> la, <span class="hljs-keyword">bool</span> create)</span> </span>{<br> <span class="hljs-comment">/* LAB2 EXERCISE 2: YOUR CODE</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * If you need to visit a physical address, please use KADDR()</span><br><span class="hljs-comment"> * please read pmm.h for useful macros</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Maybe you want help comment, BELOW comments can help you finish the code</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Some Useful MACROs and DEFINEs, you can use them in below implementation.</span><br><span class="hljs-comment"> * MACROs or Functions:</span><br><span class="hljs-comment"> * PDX(la) = the index of page directory entry of VIRTUAL ADDRESS la.</span><br><span class="hljs-comment"> * KADDR(pa) : takes a physical address and returns the corresponding kernel virtual address.</span><br><span class="hljs-comment"> * set_page_ref(page,1) : means the page be referenced by one time</span><br><span class="hljs-comment"> * page2pa(page): get the physical address of memory which this (struct Page *) page manages</span><br><span class="hljs-comment"> * struct Page * alloc_page() : allocation a page</span><br><span class="hljs-comment"> * memset(void *s, char c, size_t n) : sets the first n bytes of the memory area pointed by s</span><br><span class="hljs-comment"> * to the specified value c.</span><br><span class="hljs-comment"> * DEFINEs:</span><br><span class="hljs-comment"> * PTE_P 0x001 // page table/directory entry flags bit : Present</span><br><span class="hljs-comment"> * PTE_W 0x002 // page table/directory entry flags bit : Writeable</span><br><span class="hljs-comment"> * PTE_U 0x004 // page table/directory entry flags bit : User can access</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-keyword">pde_t</span> *pdep = &pgdir[PDX(la)];<br> <span class="hljs-comment">// 如果该条目不可用(not present)</span><br> <span class="hljs-keyword">if</span> (!(*pdep & PTE_P)) {<br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Page</span> *<span class="hljs-title">page</span>;</span><br> <span class="hljs-comment">// 如果分配页面失败,或者不允许分配,则返回NULL</span><br> <span class="hljs-keyword">if</span> (!create || (page = alloc_page()) == <span class="hljs-literal">NULL</span>)<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NULL</span>;<br> <span class="hljs-comment">// 设置该物理页面的引用次数为1</span><br> set_page_ref(page, <span class="hljs-number">1</span>);<br> <span class="hljs-comment">// 获取当前物理页面所管理的物理地址</span><br> <span class="hljs-keyword">uintptr_t</span> pa = page2pa(page);<br> <span class="hljs-comment">// 清空该物理页面的数据。需要注意的是使用虚拟地址</span><br> <span class="hljs-built_in">memset</span>(KADDR(pa), <span class="hljs-number">0</span>, PGSIZE);<br> <span class="hljs-comment">// 将新分配的页面设置为当前缺失的页目录条目中</span><br> <span class="hljs-comment">// 之后该页面就是其中的一个二级页面</span><br> *pdep = pa | PTE_U | PTE_W | PTE_P;<br> }<br> <span class="hljs-comment">// 返回在pgdir中对应于la的二级页表项</span><br> <span class="hljs-keyword">return</span> &((<span class="hljs-keyword">pte_t</span> *)KADDR(PDE_ADDR(*pdep)))[PTX(la)];<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>每一个页表项PTE都由一个32位整数来存储数据的,结构从左到右一次是:</p><table><colgroup><col style="width: 12%"><col style="width: 10%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"><col style="width: 8%"></colgroup><thead><tr class="header"><th>31-12</th><th>9-11</th><th>8</th><th>7</th><th>6</th><th>5</th><th>4</th><th>3</th><th>2</th><th>1</th><th>0</th></tr></thead><tbody><tr class="odd"><td>offset</td><td>avail</td><td>MBZ</td><td>PS</td><td>D</td><td>A</td><td>PCD</td><td>PWT</td><td>U</td><td>W</td><td>P</td></tr></tbody></table><ul><li>0 - <strong>P</strong>resent:表示当前PTE所指向的物理页面是否驻留在内存中,确认物理页是否存在</li><li>1 - <strong>W</strong>riteable: 表示是否允许读写,</li><li>2 - <strong>U</strong>ser: 表示该页的访问所需要的特权级。即User(ring3)是否允许访问,方便ucore进行权限管理</li><li>3 -<strong>P</strong>age<strong>W</strong>rite<strong>T</strong>hough:表示是否使用write through缓存写策略</li><li>4 -<strong>P</strong>age<strong>C</strong>ache<strong>D</strong>isable:表示是否<strong>不对</strong>该页进行缓存</li><li>5 - <strong>A</strong>ccess: 表示该页是否已被访问过,</li><li>6 - <strong>D</strong>irty:表示该页是否已被修改,确认数据是否有效</li><li>7 - <strong>P</strong>age<strong>S</strong>ize: 表示该页的大小</li><li>8 - <strong>M</strong>ust<strong>B</strong>e<strong>Z</strong>ero:该位必须保留为0</li><li>9-11 - <strong>Avail</strong>able:第9-11这三位并没有被内核或中断所使用,可保留给OS使用。</li><li>12-31 - Offset: 目标地址的后20位,定位物理页的位置</li></ul><p>上面一部分摘抄自 <span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.113ex" height="2.009ex" role="img" focusable="false" viewBox="0 -683 3144 888"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43E" d="M285 628Q285 635 228 637Q205 637 198 638T191 647Q191 649 193 661Q199 681 203 682Q205 683 214 683H219Q260 681 355 681Q389 681 418 681T463 682T483 682Q500 682 500 674Q500 669 497 660Q496 658 496 654T495 648T493 644T490 641T486 639T479 638T470 637T456 637Q416 636 405 634T387 623L306 305Q307 305 490 449T678 597Q692 611 692 620Q692 635 667 637Q651 637 651 648Q651 650 654 662T659 677Q662 682 676 682Q680 682 711 681T791 680Q814 680 839 681T869 682Q889 682 889 672Q889 650 881 642Q878 637 862 637Q787 632 726 586Q710 576 656 534T556 455L509 418L518 396Q527 374 546 329T581 244Q656 67 661 61Q663 59 666 57Q680 47 717 46H738Q744 38 744 37T741 19Q737 6 731 0H720Q680 3 625 3Q503 3 488 0H478Q472 6 472 9T474 27Q478 40 480 43T491 46H494Q544 46 544 71Q544 75 517 141T485 216L427 354L359 301L291 248L268 155Q245 63 245 58Q245 51 253 49T303 46H334Q340 37 340 35Q340 19 333 5Q328 0 317 0Q314 0 280 1T180 2Q118 2 85 2T49 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Z"></path></g><g data-mml-node="mi" transform="translate(889,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1234,0)"><path data-c="1D45D" d="M23 287Q24 290 25 295T30 317T40 348T55 381T75 411T101 433T134 442Q209 442 230 378L240 387Q302 442 358 442Q423 442 460 395T497 281Q497 173 421 82T249 -10Q227 -10 210 -4Q199 1 187 11T168 28L161 36Q160 35 139 -51T118 -138Q118 -144 126 -145T163 -148H188Q194 -155 194 -157T191 -175Q188 -187 185 -190T172 -194Q170 -194 161 -194T127 -193T65 -192Q-5 -192 -24 -194H-32Q-39 -187 -39 -183Q-37 -156 -26 -148H-6Q28 -147 33 -136Q36 -130 94 103T155 350Q156 355 156 364Q156 405 131 405Q109 405 94 377T71 316T59 280Q57 278 43 278H29Q23 284 23 287ZM178 102Q200 26 252 26Q282 26 310 49T356 107Q374 141 392 215T411 325V331Q411 405 350 405Q339 405 328 402T306 393T286 380T269 365T254 350T243 336T235 326L232 322Q232 321 229 308T218 264T204 212Q178 106 178 102Z"></path></g><g data-mml-node="mi" transform="translate(1737,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2188,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mi" transform="translate(2654,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g></g></g></svg></mjx-container></span></p><p>若出现了页访问异常,硬件可以</p><ul><li>将引发页访问异常的地址将被保存在cr2寄存器中</li><li>设置错误代码</li><li>引发Page Fault,将外存的数据换到内存中</li><li>进行上下文切换,退出中断,返回到中断前的状态</li></ul><h2 id="练习三">练习三</h2><p>补全在 kern/mm/pmm.c中的page_remove_pte函数,page_remove_pte的callgraph:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232059668.png" srcset="/img/loading.gif" lazyload></p><p>代码补全如下:</p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml">static inline void<br>page<span class="hljs-constructor">_remove_pte(<span class="hljs-params">pde_t</span> <span class="hljs-operator">*</span><span class="hljs-params">pgdir</span>, <span class="hljs-params">uintptr_t</span> <span class="hljs-params">la</span>, <span class="hljs-params">pte_t</span> <span class="hljs-operator">*</span><span class="hljs-params">ptep</span>)</span> {<br> <span class="hljs-comment">/* LAB2 EXERCISE 3: YOUR CODE</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Please check if ptep is valid, and tlb must be manually updated if mapping is updated</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Maybe you want help comment, BELOW comments can help you finish the code</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Some Useful MACROs and DEFINEs, you can use them in below implementation.</span><br><span class="hljs-comment"> * MACROs or Functions:</span><br><span class="hljs-comment"> * struct Page *page pte2page(*ptep): get the according page from the value of a ptep</span><br><span class="hljs-comment"> * free_page : free a page</span><br><span class="hljs-comment"> * page_ref_dec(page) : decrease page->ref. NOTICE: ff page->ref == 0 , then this page should be free.</span><br><span class="hljs-comment"> * tlb_invalidate(pde_t *pgdir, uintptr_t la) : Invalidate a TLB entry, but only if the page tables being</span><br><span class="hljs-comment"> * edited are the ones currently in use by the processor.</span><br><span class="hljs-comment"> * DEFINEs:</span><br><span class="hljs-comment"> * PTE_P 0x001 // page table/directory entry flags bit : Present</span><br><span class="hljs-comment"> */</span><br><span class="hljs-comment">//page_remove_pte - free an Page sturct which is related linear address la</span><br><span class="hljs-comment">// - and clean(invalidate) pte which is related linear address la</span><br><span class="hljs-comment">//note: PT is changed, so the TLB need to be invalidate</span><br> <span class="hljs-comment">// 如果传入的页表条目是可用的</span><br> <span class="hljs-keyword">if</span> (*ptep & PTE_P) {<br> <span class="hljs-comment">// 获取该页表条目所对应的地址</span><br> <span class="hljs-keyword">struct</span> Page *page = pte2page(*ptep);<br> <span class="hljs-comment">// 如果该页的引用次数在减1后为0</span><br> <span class="hljs-keyword">if</span> (page<span class="hljs-constructor">_ref_dec(<span class="hljs-params">page</span>)</span><span class="hljs-operator"> == </span><span class="hljs-number">0</span>)<br> <span class="hljs-comment">// 释放当前页</span><br> free<span class="hljs-constructor">_page(<span class="hljs-params">page</span>)</span>;<br> <span class="hljs-comment">// 清空PTE</span><br> *ptep = <span class="hljs-number">0</span>;<br> <span class="hljs-comment">// 刷新TLB内的数据</span><br> tlb<span class="hljs-constructor">_invalidate(<span class="hljs-params">pgdir</span>, <span class="hljs-params">la</span>)</span>;<br> }<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>此时再次执行 <code>make qemu</code> 可以看到:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232100795.png" srcset="/img/loading.gif" lazyload></p><p>小字显示check_pgdir(),ckeck_boot_pgdir()执行成功,ucore正常执行lab1中完成的功能。</p><p>显然,当页目录项或者页表项有效的时候,page数组中的项与其存在对应关系。因为pages数组记载的是物理页的信息,而在段页式存储机制中,页目录项记载页表的信息,页表记载物理页的信息。pages数组记载的数据和页目录项/页表项记载的数据指向的可能是同一个物理页。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232100480.png" srcset="/img/loading.gif" lazyload></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232100388.png" srcset="/img/loading.gif" lazyload></p><p>然后lab2提了一个问题,如何使虚拟地址与物理地址相等?</p><p>显然,由于我们现在的ucore是通过虚拟地址到物理地址的映射实现的内存管理,如果要取消该映射,我们应该反向查找lab2中的映射方式。首先是更改内核的加载地址为0,在lab2-copy中更改tools/kernel.ld,把内核的加载地址由0xc0100000修改为0x0,之后修改内核偏移地址,在kern/mm/memlayout.h中修改偏移量由0xc00000为0x0,之后关闭页机制即可。在obj/kernel_nopage.asm注释掉即可:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-meta"># enable paging</span><br><span class="hljs-meta"># movl %cr0, %eax</span><br></code></pre></div></td></tr></tbody></table></figure><p>重新make qemu,可以看到:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">+ ld bin/kernel<br>+ ld bin/kernel_nopage<br>记录了10000+0 的读入<br>记录了10000+0 的写出<br>5120000字节(5.1 MB,4.9 MiB)已复制,0.0317289 s,161 MB/s<br>记录了1+0 的读入<br>记录了1+0 的写出<br>512字节已复制,9.2267e-05 s,5.5 MB/s<br>记录了256+1 的读入<br>记录了256+1 的写出<br>131204字节(131 kB,128 KiB)已复制,0.000959132 s,137 MB/s<br>WARNING: Image format was not specified for 'bin/ucore.img' and probing guessed raw.<br> Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.<br> Specify the 'raw' format explicitly to remove the restrictions.<br></code></pre></div></td></tr></tbody></table></figure><p>程序认为这种读写形式是dangerous的,禁止了我们的读写。而这个raw实际上是原始的一种磁盘镜像格式,是一种稀疏文件。</p><h2 id="challenge-1">challenge 1</h2><p>我的建议是仔细阅读文档里给的链接:<a href="https://coolshell.cn/articles/10427.html">coolshell</a></p><blockquote><p>伙伴分配的实质就是一种特殊的<strong>“分离适配”</strong>,即将内存按2的幂进行划分,相当于分离出若干个块大小一致的空闲链表,搜索该链表并给出同需求最佳匹配的大小。其优点是快速搜索合并(O(logN)时间复杂度)以及低外部碎片(最佳适配best-fit);其缺点是内部碎片,因为按2的幂划分块,如果碰上66单位大小,那么必须划分128单位大小的块。但若需求本身就按2的幂分配,比如可以先分配若干个内存池,在其基础上进一步细分就很有吸引力了。</p></blockquote><p>要实现一个伙伴算法,且这个算法中对可用存储空间的大小划分必须是二次幂,这很容易令人想到二叉树。我们来一步一步实现。</p><p>首先是要有一个函数能够把数字转为最接近该数字的二次幂的函数。</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">size_t</span> <span class="hljs-title">getLessNearOfPower2</span><span class="hljs-params">(<span class="hljs-keyword">size_t</span> x)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">size_t</span> _i;<br> <span class="hljs-keyword">for</span>(_i = <span class="hljs-number">0</span>; _i < <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">size_t</span>) * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>; _i++)<br> <span class="hljs-keyword">if</span>((<span class="hljs-number">1</span> << (_i+<span class="hljs-number">1</span>)) > x)<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">return</span> (<span class="hljs-keyword">size_t</span>)(<span class="hljs-number">1</span> << _i);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>类比于kern/mm中对内存的管理,我们先要初始化我们的init_memmap,由于我们要按照二次幂的大小来分割我们的空间,我们可以得到这样一个内存分布,</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204232100833.png" srcset="/img/loading.gif" lazyload></p><p>假设一个内存块有1024k,当A需要70k的时候,我们从1024开始寻找一个大小为二次幂x在除以2后小于70k的内存块,即找到第一个能够刚好容纳下A的内存块。之后加入b,c,d这三个块,释放内存时合并相邻的块即可。</p><p>在<a href="https://coolshell.cn/articles/10427.html">coolshell</a>中提到了这样一种实现方法,通过一个二叉树监控管理内存,根节点监控x大小的块,第一层节点监控x/2大小的块,依次类推。具体实现细节请自行查看coolshell.</p><p>实际上我们在实现的时候可以不采用coolshell提到的struct,而是直接通过算法去抽象的完成这样一个树。</p><p><a href="https://github.com/Kiprey/Skr_Learning/blob/master/week9-19/uCore/os_kernel_lab-master_RAW/labcodes/lab2/kern/mm/buddySystem_pmm.c">Kiprey</a>就是采用双向链表实现,内存上的开销会比较小,但在双向链表中难以确定块之间的合并操作。<a href="https://github.com/ZebornDuan/UCore/blob/master/lab2/buddy.md">ZebornDuan</a>采用了二叉树实现,我决定参考他的代码写一写。</p><p>buddy.h仿照default_pmm.h即可,</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> __KERN_BUDDY_H__</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> __KERN_BUDDY_H__</span><br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><pmm.h></span></span><br><br><span class="hljs-keyword">extern</span> <span class="hljs-keyword">const</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">pmm_manager</span> <span class="hljs-title">buddy_pmm_manager</span>;</span><br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span><br></code></pre></div></td></tr></tbody></table></figure><p>主要是实现buddy.c,建议参考<a href="https://github.com/ZebornDuan/UCore/blob/master/lab2/buddy.md">github</a></p><p>这里引用一下:</p><blockquote><p>特别地,假设BuddySystem需要管理2<sup>h个物理页面,即二叉树的叶节点总共有2</sup>h个,则二叉树的结点总数为2<sup>(h+1)-1个,简单起见,这里直接算作2</sup>(h+1)个。而每个结点需要一个4字节整数来记录其可用空间,因此维护二叉树所需要的总的存储空间为2<sup>(h+3)B。一个页面的大小为4KB即2</sup>12B,因此需要的物理页数为2<sup>(h-9)页。内存成页分配,最终消耗的页数为max{1,2</sup>(h-9)}。</p><p>如果需要管理的物理页数不大于512页,则拿出其中一页用来维护信息,剩下的页数取不大于它的最大2的整数幂页来构成二叉树。如果需要管理的物理页数大于512页,设为t页,则需要求解不等式2^(h-9) + 2^h <=t,从而确定组织成多大规模的二叉树。而这样势必会造成一部分物理页既没有用来维护信息,也无法被分配,从而被浪费的情况。为了避免这种情况,可以在当存在物理页冗余的情况下,扩大二叉树的规模,这样即增大了可以被分配的物理页,也需要分配更多的页来维护信息,但一般情况下,这种方式实际获得的能够分配的物理页数是增加的,因为增加一页用来维护信息就最多可以获得512页用来分配。为了尽可能的使所有的物理页都得到利用,对于t>512的情况,直接建立最大规模的二叉树,即其叶结点数不超过t其为最大的2的整数幂,不妨设为2^h,并为这些页面分配维护其信息的页。如果总页数再加倍维护页的情况下仍然有冗余,则使维护页和分配页同时加倍。对于二叉树中无法对应到物理页中的一部分结点,可以视为其已经被分配,且永远不会被释放从,让除维护页以外所有的页面都有可能被分配出去。</p></blockquote><p>还是太菜了,也没时间,就给佬的代码写了点注释,看懂了佬的代码。</p><p>还是太菜了。</p><h2 id="challenge2不做">challenge2不做</h2><p>参考资料少,slub不太了解,科研太忙,期中考试要复习,以后有空<del>不可能的</del>在做。</p>]]></content>
<summary type="html"><h1 id="参考资料">参考资料</h1>
<p><a href="https://github.com/ZebornDuan/UCore/blob/master/lab2/buddy.md">ZebornDuan</a></p>
<p><a href="https://ki</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>ucore-lab1</title>
<link href="https://heeler-deer.top/posts/28603/"/>
<id>https://heeler-deer.top/posts/28603/</id>
<published>2022-04-16T07:37:55.000Z</published>
<updated>2023-08-29T07:44:33.754Z</updated>
<content type="html"><![CDATA[<p>RT</p><p><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.186ex" xmlns="http://www.w3.org/2000/svg" width="12.361ex" height="1.756ex" role="img" focusable="false" viewBox="0 -694 5463.4 776"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D448" d="M107 637Q73 637 71 641Q70 643 70 649Q70 673 81 682Q83 683 98 683Q139 681 234 681Q268 681 297 681T342 682T362 682Q378 682 378 672Q378 670 376 658Q371 641 366 638H364Q362 638 359 638T352 638T343 637T334 637Q295 636 284 634T266 623Q265 621 238 518T184 302T154 169Q152 155 152 140Q152 86 183 55T269 24Q336 24 403 69T501 205L552 406Q599 598 599 606Q599 633 535 637Q511 637 511 648Q511 650 513 660Q517 676 519 679T529 683Q532 683 561 682T645 680Q696 680 723 681T752 682Q767 682 767 672Q767 650 759 642Q756 637 737 637Q666 633 648 597Q646 592 598 404Q557 235 548 205Q515 105 433 42T263 -22Q171 -22 116 34T60 167V183Q60 201 115 421Q164 622 164 628Q164 635 107 637Z"></path></g><g data-mml-node="mi" transform="translate(767,0)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z"></path></g><g data-mml-node="mi" transform="translate(1200,0)"><path data-c="1D45C" d="M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z"></path></g><g data-mml-node="mi" transform="translate(1685,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2136,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mo" transform="translate(2824.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(3824.4,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g><g data-mml-node="mi" transform="translate(4505.4,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path></g><g data-mml-node="mi" transform="translate(5034.4,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g></g></g></svg></mjx-container></span> 官方文档:<a href="https://chyyuu.gitbooks.io/ucore_os_docs/content/">gitbook</a></p><p><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.186ex" xmlns="http://www.w3.org/2000/svg" width="12.361ex" height="1.756ex" role="img" focusable="false" viewBox="0 -694 5463.4 776"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D448" d="M107 637Q73 637 71 641Q70 643 70 649Q70 673 81 682Q83 683 98 683Q139 681 234 681Q268 681 297 681T342 682T362 682Q378 682 378 672Q378 670 376 658Q371 641 366 638H364Q362 638 359 638T352 638T343 637T334 637Q295 636 284 634T266 623Q265 621 238 518T184 302T154 169Q152 155 152 140Q152 86 183 55T269 24Q336 24 403 69T501 205L552 406Q599 598 599 606Q599 633 535 637Q511 637 511 648Q511 650 513 660Q517 676 519 679T529 683Q532 683 561 682T645 680Q696 680 723 681T752 682Q767 682 767 672Q767 650 759 642Q756 637 737 637Q666 633 648 597Q646 592 598 404Q557 235 548 205Q515 105 433 42T263 -22Q171 -22 116 34T60 167V183Q60 201 115 421Q164 622 164 628Q164 635 107 637Z"></path></g><g data-mml-node="mi" transform="translate(767,0)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z"></path></g><g data-mml-node="mi" transform="translate(1200,0)"><path data-c="1D45C" d="M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z"></path></g><g data-mml-node="mi" transform="translate(1685,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2136,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mo" transform="translate(2824.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(3824.4,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g><g data-mml-node="mi" transform="translate(4505.4,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path></g><g data-mml-node="mi" transform="translate(5034.4,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g></g></g></svg></mjx-container></span> 的github地址:<a href="https://github.com/chyyuu/os_kernel_lab">github</a></p><h1 id="参考博客">参考博客</h1><p><a href="https://belyenochi.github.io/2018/09/16/ucore-lab1/">belyenochi</a></p><p><a href="https://kiprey.github.io/2020/08/uCore-1/#%E7%BB%83%E4%B9%A0%E8%A7%A3%E7%AD%94">kiprey</a></p><p><a href="https://yuerer.com/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F-uCore-Lab-1/">Yuerer</a></p><p>准备工作:下载ucorelab在<span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="7.649ex" height="1.645ex" role="img" focusable="false" viewBox="0 -705 3381 727"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43A" d="M50 252Q50 367 117 473T286 641T490 704Q580 704 633 653Q642 643 648 636T656 626L657 623Q660 623 684 649Q691 655 699 663T715 679T725 690L740 705H746Q760 705 760 698Q760 694 728 561Q692 422 692 421Q690 416 687 415T669 413H653Q647 419 647 422Q647 423 648 429T650 449T651 481Q651 552 619 605T510 659Q492 659 471 656T418 643T357 615T294 567T236 496T189 394T158 260Q156 242 156 221Q156 173 170 136T206 79T256 45T308 28T353 24Q407 24 452 47T514 106Q517 114 529 161T541 214Q541 222 528 224T468 227H431Q425 233 425 235T427 254Q431 267 437 273H454Q494 271 594 271Q634 271 659 271T695 272T707 272Q721 272 721 263Q721 261 719 249Q714 230 709 228Q706 227 694 227Q674 227 653 224Q646 221 643 215T629 164Q620 131 614 108Q589 6 586 3Q584 1 581 1Q571 1 553 21T530 52Q530 53 528 52T522 47Q448 -22 322 -22Q201 -22 126 55T50 252Z"></path></g><g data-mml-node="mi" transform="translate(786,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1131,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(1492,0)"><path data-c="1D43B" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 219 683Q260 681 355 681Q389 681 418 681T463 682T483 682Q499 682 499 672Q499 670 497 658Q492 641 487 638H485Q483 638 480 638T473 638T464 637T455 637Q416 636 405 634T387 623Q384 619 355 500Q348 474 340 442T328 395L324 380Q324 378 469 378H614L615 381Q615 384 646 504Q674 619 674 627T617 637Q594 637 587 639T580 648Q580 650 582 660Q586 677 588 679T604 682Q609 682 646 681T740 680Q802 680 835 681T871 682Q888 682 888 672Q888 645 876 638H874Q872 638 869 638T862 638T853 637T844 637Q805 636 794 634T776 623Q773 618 704 340T634 58Q634 51 638 51Q646 48 692 46H723Q729 38 729 37T726 19Q722 6 716 0H701Q664 2 567 2Q533 2 504 2T458 2T437 1Q420 1 420 10Q420 15 423 24Q428 43 433 45Q437 46 448 46H454Q481 46 514 49Q520 50 522 50T528 55T534 64T540 82T547 110T558 153Q565 181 569 198Q602 330 602 331T457 332H312L279 197Q245 63 245 58Q245 51 253 49T303 46H334Q340 38 340 37T337 19Q333 6 327 0H312Q275 2 178 2Q144 2 115 2T69 2T48 1Q31 1 31 10Q31 12 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g><g data-mml-node="mi" transform="translate(2380,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2952,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g></g></g></svg></mjx-container></span>的master分支(注意不是main分支),需要用到的资料以及答案都在里面。</p><p><strong>实验环境:</strong></p><p><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="12.622ex" height="1.62ex" role="img" focusable="false" viewBox="0 -694 5579 716"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D448" d="M107 637Q73 637 71 641Q70 643 70 649Q70 673 81 682Q83 683 98 683Q139 681 234 681Q268 681 297 681T342 682T362 682Q378 682 378 672Q378 670 376 658Q371 641 366 638H364Q362 638 359 638T352 638T343 637T334 637Q295 636 284 634T266 623Q265 621 238 518T184 302T154 169Q152 155 152 140Q152 86 183 55T269 24Q336 24 403 69T501 205L552 406Q599 598 599 606Q599 633 535 637Q511 637 511 648Q511 650 513 660Q517 676 519 679T529 683Q532 683 561 682T645 680Q696 680 723 681T752 682Q767 682 767 672Q767 650 759 642Q756 637 737 637Q666 633 648 597Q646 592 598 404Q557 235 548 205Q515 105 433 42T263 -22Q171 -22 116 34T60 167V183Q60 201 115 421Q164 622 164 628Q164 635 107 637Z"></path></g><g data-mml-node="mi" transform="translate(767,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g><g data-mml-node="mi" transform="translate(1196,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1768,0)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2368,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(2729,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mn" transform="translate(3301,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(1278,0)"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1778,0)"></path></g></g></g></svg></mjx-container></span>及更高版本</p><p><strong>准备工作:</strong></p><ol type="1"><li><p>安装gcc:</p><figure class="highlight routeros"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs routeros">sudo apt-<span class="hljs-builtin-name">get</span> install build-essential<br></code></pre></div></td></tr></tbody></table></figure></li><li><p>安装qemu:</p><figure class="highlight livecodeserver"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs livecodeserver">sudo apt-<span class="hljs-built_in">get</span> install qemu-<span class="hljs-keyword">system</span><br></code></pre></div></td></tr></tbody></table></figure></li></ol><p><strong>涉及到的知识点:</strong></p><ol type="1"><li><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.025ex" xmlns="http://www.w3.org/2000/svg" width="10.011ex" height="1.595ex" role="img" focusable="false" viewBox="0 -694 4425 705"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D440" d="M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z"></path></g><g data-mml-node="mi" transform="translate(1051,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path></g><g data-mml-node="mi" transform="translate(1580,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"></path></g><g data-mml-node="mi" transform="translate(2101,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mi" transform="translate(2567,0)"><path data-c="1D439" d="M48 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H742Q749 676 749 669Q749 664 736 557T722 447Q720 440 702 440H690Q683 445 683 453Q683 454 686 477T689 530Q689 560 682 579T663 610T626 626T575 633T503 634H480Q398 633 393 631Q388 629 386 623Q385 622 352 492L320 363H375Q378 363 398 363T426 364T448 367T472 374T489 386Q502 398 511 419T524 457T529 475Q532 480 548 480H560Q567 475 567 470Q567 467 536 339T502 207Q500 200 482 200H470Q463 206 463 212Q463 215 468 234T473 274Q473 303 453 310T364 317H309L277 190Q245 66 245 60Q245 46 334 46H359Q365 40 365 39T363 19Q359 6 353 0H336Q295 2 185 2Q120 2 86 2T48 1Z"></path></g><g data-mml-node="mi" transform="translate(3316,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(3661,0)"><path data-c="1D459" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path></g><g data-mml-node="mi" transform="translate(3959,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g></g></g></svg></mjx-container></span>,建议参考<a href="https://heeler-deer.github.io/2021/10/20/makefile/">Heeler-Deer</a>,以及<a href="https://seisman.github.io/how-to-write-makefile/overview.html">博客</a></li><li>gcc,gdb等的基本使用</li><li>shell的基本使用,诸如diff,ld,readelf等命令</li></ol><p>详细请参考ucorelab的<a href="https://chyyuu.gitbooks.io/ucore_os_docs/content/lab0/lab0_ref_ucore-tools.html">官方文档</a></p><p>强烈建议在<strong>学堂在线</strong>看thu的ucore课程</p><h1 id="知识点">知识点</h1><p>先定一个小目标,学一学doxygen以及binutils的相关工具</p><h3 id="meld">meld</h3><p>先<code>sudo apt-get install meld</code>,然后就可以用了</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204191822060.png" srcset="/img/loading.gif" lazyload></p><p>这是meld官网:<a href="https://meldmerge.org/help/index.html#advanced">usage</a></p><h3 id="doxygen">doxygen</h3><p>参考<a href="https://cedar-renjun.github.io/2014/03/21/learn-doxygen-in-10-minutes/">博客</a></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204192130713.png" srcset="/img/loading.gif" lazyload></p><p>doxygen能生成latex,通过规范注释来解释项目结构。</p><p>常用命令:</p><figure class="highlight nginx"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs nginx"><span class="hljs-attribute">doxygen</span> -g <span class="hljs-comment">#生成Doxygenfile</span><br></code></pre></div></td></tr></tbody></table></figure><figure class="highlight jboss-cli"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs jboss-cli">doxygen <span class="hljs-string">./Doxyfile</span> <span class="hljs-comment">#生成文档</span><br></code></pre></div></td></tr></tbody></table></figure><p>注释规范:</p><figure class="highlight actionscript"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs actionscript"><span class="hljs-comment">/*</span><br><span class="hljs-comment"> * 正常注释</span><br><span class="hljs-comment"> */</span><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 要输出成文档的注释</span><br><span class="hljs-comment"> */</span><br><br> 或者<br><br><span class="hljs-comment">/*!</span><br><span class="hljs-comment"> * 要输出成文档的注释</span><br><span class="hljs-comment"> */</span><br></code></pre></div></td></tr></tbody></table></figure><p>或者是:</p><figure class="highlight markdown"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs markdown">//<span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">**<span class="hljs-emphasis">*</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//! \brief Print Int number to terimal device.</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//!</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//! \param [in] number is the data you want to print.</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//! \retval the number of print information, in bytes. return zero indicate print error !.</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//!</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//! \note</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//! *</span> Be sure you have called \ref Dev<span class="hljs-emphasis">_Init function before call this fuction.</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//! * Remember to check return value.</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//</span></span><br><span class="hljs-emphasis"><span class="hljs-strong">//<span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">****</span><span class="hljs-strong">**<span class="hljs-emphasis">*</span></span></span></span><br><span class="hljs-emphasis"><span class="hljs-strong"><span class="hljs-emphasis"><span class="hljs-strong">extern int Dev_PrintInt(int number);</span></span></span></span><br></code></pre></div></td></tr></tbody></table></figure><h3 id="binutils">binutils</h3><p>binutils包含很多命令,不详细介绍了,列举一下:</p><ul><li><p><strong>ld</strong> - the GNU linker.</p></li><li><p><strong>as</strong> - the GNU assembler.</p></li><li><p><strong>addr2line</strong> - Converts addresses into filenamesand line numbers.</p></li><li><p><strong>ar</strong> - A utility for creating, modifying andextracting from archives.</p></li><li><p><strong>c++filt</strong> - Filter to demangle encoded C++symbols.</p></li><li><p><strong>dlltool</strong> - Creates files for building and usingDLLs.</p></li><li><p><strong>gold</strong> - A new, faster, ELF only linker, still inbeta test.</p></li><li><p><strong>gprof</strong> - Displays profiling information.</p></li><li><p><strong>nlmconv</strong> - Converts object code into anNLM.</p></li><li><p><strong>nm</strong> - Lists symbols from object files.</p></li><li><p><strong>objcopy</strong> - Copies and translates objectfiles.</p></li><li><p><strong>objdump</strong> - Displays information from objectfiles.</p></li><li><p><strong>ranlib</strong> - Generates an index to the contents ofan archive.</p></li><li><p><strong>readelf</strong> - Displays information from any ELFformat object file.</p></li><li><p><strong>size</strong> - Lists the section sizes of an object orarchive file.</p></li><li><p><strong>strings</strong> - Lists printable strings fromfiles.</p></li><li><p><strong>strip</strong> - Discards symbols.</p></li><li><p><strong>windmc</strong> - A Windows compatible messagecompiler.</p></li><li><p><strong>windres</strong> - A compiler for Windows resourcefiles.</p></li></ul><h2 id="系统启动及中断">系统启动及中断</h2><p>bios提供了基本的i/o功能</p><p>cpu加电后执行ROM里的初始化代码:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204192158253.png" srcset="/img/loading.gif" lazyload></p><p>从硬盘/网络启动是由bios决定,bios加载程序到磁盘的引导扇区,跳转到cs:ip=0000:7c00,读取加载程序,用加载程序识别文件系统,识别文件系统之后就可以读取os的内核代码,在把控制权转给os:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204192202995.png" srcset="/img/loading.gif" lazyload></p><p>bios和uefi的区别:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204192216709.png" srcset="/img/loading.gif" lazyload></p><p>中断(来自硬件)、异常(非法指令等)、系统调用(应用程序主动向os发的请求):</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204192223617.png" srcset="/img/loading.gif" lazyload></p><p>计算机对上述三种情况采用的中断处理机制:</p><ol type="1"><li><p>cpu初始化时设置中断使能,设置中断标志,根据中断向量调用相关中断服务例程</p></li><li><p>软件处理:</p></li></ol><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204192230246.png" srcset="/img/loading.gif" lazyload></p><p>中断是可以嵌套的,也就是异常里可以出现异常 <span class="github-emoji"><span>🤔</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f914.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><p>系统调用采用int和iret指令,可以进行堆栈切换以及特权级的转换,函数调用采用call和ret指令,一般情况下没有堆栈切换</p><p>遗漏的知识点参考kiprey,仅记录本人不熟悉的知识点</p><h3 id="bioslinuxdos中断的区别">bios/linux/dos中断的区别</h3><p>bios/dos建立在实模式下,他们建立的中断调用都采用中断向量表,linux则是在进入保护模式后才建立中断例程,通过中断描述符表idt实现中断</p><h3 id="文件">文件</h3><p>os通过文件系统的magicnumber得知文件系统类型,一般在分区的第二个扇区</p><h3 id="实模式">实模式</h3><p>实模式的主要特性是:<strong>程序用到的地址都是真实的物理地址</strong>。同时,实模式下的地址寻址空间只有1MB(20bit)</p><blockquote><p>从intel 80386开始的CPU,只要进入实模式,地址寻址空间就限制在1MB。</p></blockquote><p>实模式下的地址计算方式为<strong>16*段寄存器值+段内偏移地址</strong>,其CPU寻址方式为</p><ul><li>寄存器寻址</li><li>立即数寻址</li><li>内存寻址</li><li>直接寻址。</li><li>基址寻址</li><li>变址寻址</li><li>基址变址寻址</li></ul><p>在分段存储管理机制的保护模式下,每个段由如下三个参数进行定义:段基地址(BaseAddress)、段界限(Limit)和段属性(Attributes)</p><ul><li>段基地址:规定线性地址空间中段的起始地址。任何一个段都可以从32位线性地址空间中的任何一个字节开始,不用像实模式下规定边界必须被16整除。</li><li>段界限:规定段的大小。可以以字节为单位或以4K字节为单位。</li><li>段属性:确定段的各种性质。</li></ul><p>全局描述符表(GDT)是一个保存多个段描述符的“数组”,其起始地址保存在全局描述符表寄存器GDTR中。GDTR长48位,其中高32位为基地址,低16位为段界限</p><p>线性地址部分的选择子是用来选择哪个描述符表和在该表中索引哪个描述符的。选择子可以做为指针变量的一部分,从而对应用程序员是可见的,但是一般是由连接加载器来设置的。</p><p>段选择子结构</p><ul><li>索引(Index):在描述符表中从8192个描述符中选择一个描述符。处理器自动将这个索引值乘以8(描述符的长度),再加上描述符表的基址来索引描述符表,从而选出一个合适的描述符。</li><li>表指示位(TableIndicator,TI):选择应该访问哪一个描述符表。0代表应该访问全局描述符表(GDT),1代表应该访问局部描述符表(LDT)。</li><li>请求特权级(Requested Privilege Level,RPL):保护机制</li></ul><h3 id="中断与异常">中断与异常</h3><p>在操作系统中,有三种特殊的中断事件:</p><ul><li>异步中断(asynchronousinterrupt)。这是由CPU外部设备引起的外部事件中断,例如I/O中断、时钟中断、控制台中断等。</li><li>同步中断(synchronousinterrupt)。这是CPU执行指令期间检测到不正常的或非法的条件(如除零错、地址访问越界)所引起的内部事件。</li><li>陷入中断(trapinterrupt)。这是在程序中使用请求系统服务的系统调用而引发的事件。</li></ul><p>IDT中包含了3种类型的Descriptor</p><ul><li>Task-gate descriptor</li><li>Interrupt-gate descriptor (中断方式用到)</li><li>Trap-gate descriptor(系统调用用到)</li></ul><h3 id="特权">特权</h3><p>特权级共分为四档,分别为0-3,其中<code>Kernel</code>为第0特权级(ring0),用户程序为第3特权级(ring3),操作系统保护分别为第1和第2特权级。</p><ul><li><p><strong>DPL存储于段描述符中</strong>,规定<strong>访问该段的权限级别</strong>(DescriptorPrivilege Level),每个段的DPL固定。当进程访问一个段时,需要进程特权级检查。</p></li><li><p><strong>CPL</strong>存在于CS寄存器的低两位,<strong>即CPL是CS段描述符的DPL</strong>,是当前代码的权限级别(CurrentPrivilege Level)。</p></li><li><p><strong>RPL存在于段选择子中</strong>,说明的是<strong>进程对段访问的请求权限</strong>(RequestPrivilegeLevel),是对于<strong>段选择子</strong>而言的,每个段选择子有自己的RPL。而且RPL对每个段来说不是固定的,两次访问同一段时的RPL可以不同。RPL可能会削弱CPL的作用,例如当前CPL=0的进程要访问一个数据段,它把段选择符中的RPL设为3,这样虽然它对该段仍然只有特权为3的访问权限。</p></li><li><p>IOPL(I/O PrivilegeLevel)即I/O特权标志,位于<strong>eflag寄存器</strong>中,用两位二进制位来表示,也称为I/O特权级字段。该字段指定了要求执行I/O指令的特权级。如果当前的特权级别在数值上小于等于IOPL的值,那么,该I/O指令可执行,否则将发生一个保护异常。</p><blockquote><p>只有当CPL=0时,可以改变IOPL的值,当CPL<=IOPL时,可以改变IF标志位。</p></blockquote></li><li><p>访问门时(中断、陷入、异常),要求<strong>DPL[段] <= CPL <=DPL[门]</strong></p><blockquote><p>访问门的代码权限<strong>比门的特权级要高</strong>,因为这样才能访问门。</p><p>但访问门的代码权限<strong>比被访问的段的权限要低</strong>,因为通过门的目的是<strong>访问特权级更高的段</strong>,这样就可以达到<strong>低权限应用程序使用高权限内核服务</strong>的目的。</p></blockquote></li><li><p>访问段时,要求<strong>DPL[段] >= max {CPL, RPL}</strong></p><blockquote><p>只能使用最低的权限来访问段数据。</p></blockquote></li></ul><p><strong>TSS(Task State Segment)</strong>是操作系统在进行进程切换时保存进程现场信息的段</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204202353757.png" srcset="/img/loading.gif" lazyload></p><p><code>trapframe</code>结构是进入中断门所必须的结构,其结构如下</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs cpp"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">trapframe</span> {</span><br> <span class="hljs-comment">// tf_regs保存了基本寄存器的值,包括eax,ebx,esi,edi寄存器等等</span><br> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">pushregs</span> <span class="hljs-title">tf_regs</span>;</span><br> <span class="hljs-keyword">uint16_t</span> tf_gs;<br> <span class="hljs-keyword">uint16_t</span> tf_padding0;<br> <span class="hljs-keyword">uint16_t</span> tf_fs;<br> <span class="hljs-keyword">uint16_t</span> tf_padding1;<br> <span class="hljs-keyword">uint16_t</span> tf_es;<br> <span class="hljs-keyword">uint16_t</span> tf_padding2;<br> <span class="hljs-keyword">uint16_t</span> tf_ds;<br> <span class="hljs-keyword">uint16_t</span> tf_padding3;<br> <span class="hljs-keyword">uint32_t</span> tf_trapno;<br> <span class="hljs-comment">// 以下这些信息会被CPU硬件自动压入切换后的栈。包括下面切换特权级所使用的esp、ss等数据</span><br> <span class="hljs-keyword">uint32_t</span> tf_err;<br> <span class="hljs-keyword">uintptr_t</span> tf_eip;<br> <span class="hljs-keyword">uint16_t</span> tf_cs;<br> <span class="hljs-keyword">uint16_t</span> tf_padding4;<br> <span class="hljs-keyword">uint32_t</span> tf_eflags;<br> <span class="hljs-comment">// 以下这些信息会在切换特权级时被使用</span><br> <span class="hljs-keyword">uintptr_t</span> tf_esp;<br> <span class="hljs-keyword">uint16_t</span> tf_ss;<br> <span class="hljs-keyword">uint16_t</span> tf_padding5;<br>} __attribute__((packed));<br></code></pre></div></td></tr></tbody></table></figure><p>以上内容大部分复制自kiprey,不知道kiprey佬是在那里学的</p><h1 id="ucore_lab1">ucore_lab1</h1><p><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.186ex" xmlns="http://www.w3.org/2000/svg" width="13.492ex" height="1.756ex" role="img" focusable="false" viewBox="0 -694 5963.4 776"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D448" d="M107 637Q73 637 71 641Q70 643 70 649Q70 673 81 682Q83 683 98 683Q139 681 234 681Q268 681 297 681T342 682T362 682Q378 682 378 672Q378 670 376 658Q371 641 366 638H364Q362 638 359 638T352 638T343 637T334 637Q295 636 284 634T266 623Q265 621 238 518T184 302T154 169Q152 155 152 140Q152 86 183 55T269 24Q336 24 403 69T501 205L552 406Q599 598 599 606Q599 633 535 637Q511 637 511 648Q511 650 513 660Q517 676 519 679T529 683Q532 683 561 682T645 680Q696 680 723 681T752 682Q767 682 767 672Q767 650 759 642Q756 637 737 637Q666 633 648 597Q646 592 598 404Q557 235 548 205Q515 105 433 42T263 -22Q171 -22 116 34T60 167V183Q60 201 115 421Q164 622 164 628Q164 635 107 637Z"></path></g><g data-mml-node="mi" transform="translate(767,0)"><path data-c="1D450" d="M34 159Q34 268 120 355T306 442Q362 442 394 418T427 355Q427 326 408 306T360 285Q341 285 330 295T319 325T330 359T352 380T366 386H367Q367 388 361 392T340 400T306 404Q276 404 249 390Q228 381 206 359Q162 315 142 235T121 119Q121 73 147 50Q169 26 205 26H209Q321 26 394 111Q403 121 406 121Q410 121 419 112T429 98T420 83T391 55T346 25T282 0T202 -11Q127 -11 81 37T34 159Z"></path></g><g data-mml-node="mi" transform="translate(1200,0)"><path data-c="1D45C" d="M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z"></path></g><g data-mml-node="mi" transform="translate(1685,0)"><path data-c="1D45F" d="M21 287Q22 290 23 295T28 317T38 348T53 381T73 411T99 433T132 442Q161 442 183 430T214 408T225 388Q227 382 228 382T236 389Q284 441 347 441H350Q398 441 422 400Q430 381 430 363Q430 333 417 315T391 292T366 288Q346 288 334 299T322 328Q322 376 378 392Q356 405 342 405Q286 405 239 331Q229 315 224 298T190 165Q156 25 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 114 189T154 366Q154 405 128 405Q107 405 92 377T68 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2136,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mo" transform="translate(2824.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"></path></g><g data-mml-node="mi" transform="translate(3824.4,0)"><path data-c="1D43F" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g><g data-mml-node="mi" transform="translate(4505.4,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path></g><g data-mml-node="mi" transform="translate(5034.4,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g><g data-mml-node="mn" transform="translate(5463.4,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path></g></g></g></svg></mjx-container></span>没什么需要做的,主要是为了后面的内容,需要点一下相关知识点。</p><h2 id="练习1">练习1</h2><ul><li>理解通过make生成执行文件的过程。</li></ul><p>在os_kernel_lab-master/labcodes/lab1/Makefile中,可以找到要分析的makefile。</p><p>makefile的结构如下:</p><figure class="highlight jboss-cli"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs jboss-cli">target.<span class="hljs-string">..</span><span class="hljs-function">:prerequisites...</span><br> <span class="hljs-keyword">command</span><br> <span class="hljs-string">...</span><br> <span class="hljs-string">...</span><br></code></pre></div></td></tr></tbody></table></figure><p>我们通过:</p><figure class="highlight applescript"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs applescript">❯ make V= >> <span class="hljs-literal">result</span>.txt<br></code></pre></div></td></tr></tbody></table></figure><p>来查看make到底执行了那些命令。</p><p>直接看<span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.025ex" xmlns="http://www.w3.org/2000/svg" width="10.011ex" height="1.595ex" role="img" focusable="false" viewBox="0 -694 4425 705"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D440" d="M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z"></path></g><g data-mml-node="mi" transform="translate(1051,0)"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path></g><g data-mml-node="mi" transform="translate(1580,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"></path></g><g data-mml-node="mi" transform="translate(2101,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g><g data-mml-node="mi" transform="translate(2567,0)"><path data-c="1D439" d="M48 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H742Q749 676 749 669Q749 664 736 557T722 447Q720 440 702 440H690Q683 445 683 453Q683 454 686 477T689 530Q689 560 682 579T663 610T626 626T575 633T503 634H480Q398 633 393 631Q388 629 386 623Q385 622 352 492L320 363H375Q378 363 398 363T426 364T448 367T472 374T489 386Q502 398 511 419T524 457T529 475Q532 480 548 480H560Q567 475 567 470Q567 467 536 339T502 207Q500 200 482 200H470Q463 206 463 212Q463 215 468 234T473 274Q473 303 453 310T364 317H309L277 190Q245 66 245 60Q245 46 334 46H359Q365 40 365 39T363 19Q359 6 353 0H336Q295 2 185 2Q120 2 86 2T48 1Z"></path></g><g data-mml-node="mi" transform="translate(3316,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(3661,0)"><path data-c="1D459" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path></g><g data-mml-node="mi" transform="translate(3959,0)"><path data-c="1D452" d="M39 168Q39 225 58 272T107 350T174 402T244 433T307 442H310Q355 442 388 420T421 355Q421 265 310 237Q261 224 176 223Q139 223 138 221Q138 219 132 186T125 128Q125 81 146 54T209 26T302 45T394 111Q403 121 406 121Q410 121 419 112T429 98T420 82T390 55T344 24T281 -1T205 -11Q126 -11 83 42T39 168ZM373 353Q367 405 305 405Q272 405 244 391T199 357T170 316T154 280T149 261Q149 260 169 260Q282 260 327 284T373 353Z"></path></g></g></g></svg></mjx-container></span>,查询关键字ucore.img,可以发现这样一段代码:</p><figure class="highlight routeros"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs routeros"><span class="hljs-comment"># create ucore.img</span><br>UCOREIMG:= $(call totarget,ucore.img)<br><br>$(UCOREIMG): $(kernel) $(bootblock)<br>$(V)dd <span class="hljs-attribute">if</span>=/dev/zero <span class="hljs-attribute">of</span>=<span class="hljs-variable">$@</span> <span class="hljs-attribute">count</span>=10000<br>$(V)dd <span class="hljs-attribute">if</span>=$(bootblock) <span class="hljs-attribute">of</span>=<span class="hljs-variable">$@</span> <span class="hljs-attribute">conv</span>=notrunc<br>$(V)dd <span class="hljs-attribute">if</span>=$(kernel) <span class="hljs-attribute">of</span>=<span class="hljs-variable">$@</span> <span class="hljs-attribute">seek</span>=1 <span class="hljs-attribute">conv</span>=notrunc<br><br>$(call create_target,ucore.img)<br></code></pre></div></td></tr></tbody></table></figure><p>也就是说要生成ucore.img,会先生成bootblock,kernel这两个target,我们依次找寻生成bootblock、kernel所需要的文件,得到这样一个文件树:</p><pre><code class="mermaid" type="">graph LR ucore-->bootblock ucore-->kernel bmo[(bootmain.o)] bso[(bootasm.o)] bootblock-->bso bootblock-->bmo bootblock-->sign bsos[(bootasm.S)] bso-->bsos bmoc[(bootmain.c)] bmo-->bmoc sign-->sign.c num[(kernel.ld等)] kernel-->num</code></pre><p>对于ucore:</p><figure class="highlight routeros"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs routeros">UCOREIMG:= $(call totarget,ucore.img)<br><br>$(UCOREIMG): $(kernel) $(bootblock)<br>$(V)dd <span class="hljs-attribute">if</span>=/dev/zero <span class="hljs-attribute">of</span>=<span class="hljs-variable">$@</span> <span class="hljs-attribute">count</span>=10000<br>$(V)dd <span class="hljs-attribute">if</span>=$(bootblock) <span class="hljs-attribute">of</span>=<span class="hljs-variable">$@</span> <span class="hljs-attribute">conv</span>=notrunc<br>$(V)dd <span class="hljs-attribute">if</span>=$(kernel) <span class="hljs-attribute">of</span>=<span class="hljs-variable">$@</span> <span class="hljs-attribute">seek</span>=1 <span class="hljs-attribute">conv</span>=notrunc<br><br>$(call create_target,ucore.img)<br></code></pre></div></td></tr></tbody></table></figure><p>其中dd命令和cp差不多,但dd更多的针对底层文件的复制.</p><p>if和ifeq差不多,仍是实现条件判断的语句,实际上是判断后面的文件是否存在,比如/dev/zero就存在于linux的/dev/目录下</p><p>of以及后面的语句则是对参数进行赋值,count指定是10000个块的字节,之后从第一个块写入bootblock的内容,seek则是指定从第二个块开始写入kernel的内容,有点类似于<a href="https://heeler-deer.github.io/2022/04/06/%E5%AF%B9udisk%E6%93%8D%E4%BD%9C/">sg_read</a></p><p>生成bootasm.o时的实际命令为:</p><figure class="highlight stata"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stata"> gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs \<br>-nostdinc -fno-<span class="hljs-keyword">stack</span>-protector -Ilibs/ -Os -nostdinc \<br>-c <span class="hljs-keyword">boot</span>/bootasm.S -o obj/<span class="hljs-keyword">boot</span>/bootasm.o<br></code></pre></div></td></tr></tbody></table></figure><p>解释一下参数:</p><p>-fno-builtin指若函数前没有builtin则不进行内部函数的优化(如下图),-Wall就是生成警告信息,-ggdb生成gdb调试信息,-m32就是按照32位机器生成代码,-gstabs生成stabs格式的调试信息,-nostdinc不是用标准库,-fno-stack-protector关闭栈保护,-Os是优化选项,-Iboot/指在boot下生成文件。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161708193.png" srcset="/img/loading.gif" lazyload></p><p>生成sign的实际命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">gcc -Itools/ -g -Wall -O2 -c tools/sign.c \<br>-o obj/sign/tools/sign.o<br>gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign<br></code></pre></div></td></tr></tbody></table></figure><p>在有了sing,bootasm.o,bootmain.o后,makefile生成bootblock.o:</p><figure class="highlight apache"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs apache"><span class="hljs-attribute">ld</span> -m elf_i<span class="hljs-number">386</span> -nostdlib -N -e start -Ttext <span class="hljs-number">0</span>x<span class="hljs-number">7</span>C<span class="hljs-number">00</span> \<br><span class="hljs-attribute">obj</span>/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o<br></code></pre></div></td></tr></tbody></table></figure><p>ld是连接器,详细用法我参考的是<a href="https://www.computerhope.com/unix/uld.htm">computerhope</a></p><p>上面的代码实际上是模拟了i386的连接器(-melf_i386),-nostdlib即不准使用标准库,-N设置代码段以及数据段均可读写,-e指定了入口是start,-Text指定了代码段的开始位置。</p><p>最后就是使用sign处理bootblock.o,首先<code>objcopy -S -O binary obj/bootblock.o obj/bootblock.out</code>,实际上-S移除了所有符号和重定位信息,-O指定输出格式,sign在处理bootblock.out生成bootblock</p><p>对于kernel,实际上没有用到多少新的参数。只需要注意ld的参数-T <script > 是让ld使用指定的script即可。</p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml"><span class="hljs-constructor">$(<span class="hljs-params">kernel</span>)</span>: tools/kernel.ld<br><span class="hljs-constructor">$(<span class="hljs-params">kernel</span>)</span>: <span class="hljs-constructor">$(KOBJS)</span><br>@echo + ld $@<br><span class="hljs-constructor">$(V)</span><span class="hljs-constructor">$(LD)</span> <span class="hljs-constructor">$(LDFLAGS)</span> -T tools/kernel.ld -o $@ <span class="hljs-constructor">$(KOBJS)</span><br>@<span class="hljs-constructor">$(OBJDUMP)</span> -S $@ > <span class="hljs-constructor">$(<span class="hljs-params">call</span> <span class="hljs-params">asmfile</span>,<span class="hljs-params">kernel</span>)</span><br>@<span class="hljs-constructor">$(OBJDUMP)</span> -t $@ <span class="hljs-pattern-match">| <span class="hljs-constructor">$(SED)</span> '1,<span class="hljs-operator">/</span><span class="hljs-constructor">SYMBOL</span> <span class="hljs-constructor">TABLE</span><span class="hljs-operator">/</span>d; s<span class="hljs-operator">/</span> .<span class="hljs-operator">*</span> <span class="hljs-operator">/</span> <span class="hljs-operator">/</span>; \</span><br><span class="hljs-pattern-match"><span class="hljs-operator">/</span>^<span class="hljs-constructor">$$</span><span class="hljs-operator">/</span>d' > <span class="hljs-constructor">$(<span class="hljs-params">call</span> <span class="hljs-params">symfile</span>,<span class="hljs-params">kernel</span>)</span></span><br></code></pre></div></td></tr></tbody></table></figure><ul><li>一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?</li></ul><p>我们可以看sign.c,一个磁盘主引导扇区只有512字节,且第510个是0x55,第511个是0xAA</p><h2 id="练习2">练习2</h2><p>参考真正の佬<a href="https://kiprey.github.io/2020/08/uCore-1/#%E7%BB%83%E4%B9%A0%E8%A7%A3%E7%AD%94">kiprey</a></p><p>修改tools/gdbinit:</p><figure class="highlight apache"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs apache"><span class="hljs-attribute">file</span> obj/bootblock.o<br><span class="hljs-attribute">set</span> architecture i<span class="hljs-number">8086</span><br><span class="hljs-attribute">target</span> remote :<span class="hljs-number">1234</span><br><span class="hljs-attribute">b</span>* <span class="hljs-number">0</span>x<span class="hljs-number">7</span>c<span class="hljs-number">00</span><br><br><span class="hljs-attribute">define</span> hook-stop<br><span class="hljs-attribute">x</span>/i $eip<br><span class="hljs-attribute">end</span><br><span class="hljs-attribute">continue</span><br></code></pre></div></td></tr></tbody></table></figure><p>其中define hook-step ...end告诉gdb在每一次断点时自动输出下一条指令。</p><p>之后make debug:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161740543.png" srcset="/img/loading.gif" lazyload></p><p>单步跟踪使用si即可,这是continue的结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161745960.png" srcset="/img/loading.gif" lazyload></p><p>设置断点:</p><p>修改gdbinit为:</p><figure class="highlight apache"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs apache"><span class="hljs-attribute">file</span> obj/bootblock.o<br><span class="hljs-attribute">set</span> architecture i<span class="hljs-number">8086</span><br><span class="hljs-attribute">target</span> remote :<span class="hljs-number">1234</span><br><span class="hljs-attribute">b</span>* <span class="hljs-number">0</span>x<span class="hljs-number">7</span>c<span class="hljs-number">00</span><br><br><span class="hljs-attribute">define</span> hook-stop<br><span class="hljs-attribute">x</span>/i $eip<br><span class="hljs-attribute">end</span><br></code></pre></div></td></tr></tbody></table></figure><p>之后make debug,输入<code>x/5i (($cs <<4)+$eip)</code>得到:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161754838.png" srcset="/img/loading.gif" lazyload></p><p>修改为:</p><figure class="highlight apache"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs apache"><span class="hljs-attribute">file</span> obj/bootblock.o<br><span class="hljs-attribute">set</span> architecture i<span class="hljs-number">8086</span><br><span class="hljs-attribute">target</span> remote :<span class="hljs-number">1234</span><br><span class="hljs-attribute">b</span>* <span class="hljs-number">0</span>x<span class="hljs-number">7</span>c<span class="hljs-number">00</span><br><br><span class="hljs-attribute">define</span> hook-stop<br><span class="hljs-attribute">c</span><br><span class="hljs-attribute">x</span> /<span class="hljs-number">10</span>i $pc<br><span class="hljs-attribute">end</span><br></code></pre></div></td></tr></tbody></table></figure><p>输入<code>qemu-system-i386 -hda yourpath/os_kernel_lab-master/labcodes/lab1/bin/ucore.img -s -S -d in_asm -D q.log</code>打开ucore,打开gdb,输入<code>target remote localhost:1234</code>,之后单步调试si得到:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161812996.png" srcset="/img/loading.gif" lazyload></p><p>可以看到0x7c00处的代码和bootasm.S处的代码一致</p><h2 id="练习3">练习3</h2><p>在bootblock.asm中,通过注释不难发现,disableinterrupts禁用了中断,之后初始化了DS,ES,SS这三个寄存器的值,都先置0,之后enableA20,开启原因在注释里面也有:</p><p>physical address line 20 is tied low ,that addresses higher than1MB.因此我们需要开启A20去兼容早期的回绕特征。kipery这样解释:</p><blockquote><ul><li>Intel早期的8086CPU提供了20根地址线,但寄存器只有16位,所以使用<strong>段寄存器值<< 4 +段内偏移值</strong>的方法来访问到所有内存,但按这种方式来计算出的地址的最大值为1088KB,超过20根地址线所能表示的范围,会发生“回卷”(和整数溢出有点类似)。但下一代的基于Intel80286CPU的计算机系统提供了24根地址线,当CPU计算出的地址超过1MB时便<strong>不会发生回卷</strong>,而这就造成了<strong>向下不兼容</strong>。为了保持完全的向下兼容性,IBM在计算机系统上加个硬件逻辑来模仿早期的回绕特征,而这就是<strong>A20Gate</strong>。</li><li>A20Gate的方法是把A20地址线控制和键盘控制器的一个输出进行AND操作,这样来控制A20地址线的打开(使能)和关闭(屏蔽)。一开始时A20地址线控制是被屏蔽的(总为0),直到系统软件通过一定的IO操作去打开它。当A20地址线控制禁止时,则程序就像在8086中运行,1MB以上的地址不可访问;保护模式下A20地址线控制必须打开。A20控制打开后,内存寻址将不会发生回卷。</li><li>在当前环境中,所用到的键盘控制器8042的IO端口只有0x60和0x64两个端口。8042通过这些端口给键盘控制器或键盘发送命令或读取状态。输出端口P2用于特定目的。位0(P20引脚)用于实现CPU复位操作,位1(P21引脚)用于控制A20信号线的开启与否。</li></ul></blockquote><p>接下来就是加载gdt这个全局描述符表,最后重新使用32位模式,重新切回到保护模式。</p><p>在bootasm.S中,</p><p>初始化了gdt:</p><figure class="highlight jboss-cli"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs jboss-cli"><span class="hljs-comment"># Bootstrap GDT</span><br><span class="hljs-string">.p2align</span> 2 <span class="hljs-comment"># force 4 byte alignment</span><br>gdt:<br> SEG_NULLASM <span class="hljs-comment"># null seg</span><br> SEG_ASM<span class="hljs-params">(STA_X|STA_R, 0x0, 0xffffffff)</span> <span class="hljs-comment"># code seg for bootloader and kernel</span><br> SEG_ASM<span class="hljs-params">(STA_W, 0x0, 0xffffffff)</span> <span class="hljs-comment"># data seg for bootloader and kernel</span><br><br>gdtdesc:<br> <span class="hljs-string">.word</span> 0x17 <span class="hljs-comment"># sizeof(gdt) - 1</span><br> <span class="hljs-string">.long</span> gdt <br></code></pre></div></td></tr></tbody></table></figure><p>看注释即可理解。bootasm.s中的代码设置了CR0_PE_ON来返回保护模式:</p><figure class="highlight cos"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs cos">.<span class="hljs-keyword">set</span> CR0_PE_ON, <span class="hljs-number">0</span>x1 # protected mode enable flag<br>.........<br>lgdt gdtdesc<br> movl <span class="hljs-built_in">%cr</span>0, <span class="hljs-built_in">%eax</span><br> orl <span class="hljs-built_in">$CR</span>0_PE_ON, <span class="hljs-built_in">%eax</span><br> movl <span class="hljs-built_in">%eax</span>, <span class="hljs-built_in">%cr</span>0<br></code></pre></div></td></tr></tbody></table></figure><h2 id="练习4">练习4</h2><p>ELF文件结构:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161828865.png" srcset="/img/loading.gif" lazyload></p><p>在bootmain.c中,bootloader为了读取扇区,采用了下面的代码:</p><figure class="highlight less"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs less"><span class="hljs-comment">/* waitdisk - wait for disk ready */</span><br><span class="hljs-selector-tag">static</span> <span class="hljs-selector-tag">void</span><br><span class="hljs-selector-tag">waitdisk</span>(void) {<br> <span class="hljs-selector-tag">while</span> ((inb(<span class="hljs-number">0</span>x1F7) & <span class="hljs-number">0</span>xC0) != <span class="hljs-number">0</span>x40)<br> <span class="hljs-comment">/* do nothing */</span>;<br>}<br><br><span class="hljs-comment">/* readsect - read a single sector at @secno into @dst */</span><br><span class="hljs-selector-tag">static</span> <span class="hljs-selector-tag">void</span><br><span class="hljs-selector-tag">readsect</span>(void *dst, uint32_t secno) {<br> <span class="hljs-comment">// wait for disk to be ready</span><br> <span class="hljs-selector-tag">waitdisk</span>();<br><br> <span class="hljs-selector-tag">outb</span>(<span class="hljs-number">0</span>x1F2, <span class="hljs-number">1</span>); <span class="hljs-comment">// count = 1</span><br> <span class="hljs-selector-tag">outb</span>(<span class="hljs-number">0</span>x1F3, secno & <span class="hljs-number">0</span>xFF);<br> <span class="hljs-selector-tag">outb</span>(<span class="hljs-number">0</span>x1F4, (secno >> <span class="hljs-number">8</span>) & <span class="hljs-number">0</span>xFF);<br> <span class="hljs-selector-tag">outb</span>(<span class="hljs-number">0</span>x1F5, (secno >> <span class="hljs-number">16</span>) & <span class="hljs-number">0</span>xFF);<br> <span class="hljs-selector-tag">outb</span>(<span class="hljs-number">0</span>x1F6, ((secno >> <span class="hljs-number">24</span>) & <span class="hljs-number">0</span>xF) | <span class="hljs-number">0</span>xE0);<br> <span class="hljs-selector-tag">outb</span>(<span class="hljs-number">0</span>x1F7, <span class="hljs-number">0</span>x20); <span class="hljs-comment">// cmd 0x20 - read sectors</span><br><br> <span class="hljs-comment">// wait for disk to be ready</span><br> <span class="hljs-selector-tag">waitdisk</span>();<br><br> <span class="hljs-comment">// read a sector</span><br> <span class="hljs-selector-tag">insl</span>(<span class="hljs-number">0</span>x1F0, dst, SECTSIZE / <span class="hljs-number">4</span>);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>即先waitdisk,等待磁盘,然后写入0x1f2~0x1f5,0x1f7,准备读取磁盘,磁盘准备好时再调用insl读取到内存。</p><p>bootloader先将os加载到:</p><figure class="highlight lasso"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs lasso">#define ELFHDR ((struct elfhdr *)<span class="hljs-number">0x10000</span>) <br><span class="hljs-params">...</span><span class="hljs-params">...</span><span class="hljs-params">...</span>..<br>readseg((uintptr_t)ELFHDR, SECTSIZE * <span class="hljs-number">8</span>, <span class="hljs-number">0</span>);<br></code></pre></div></td></tr></tbody></table></figure><p>在比对elf文件的magicnumber来判断elf文件的正确性,最后在加载elf的每一个段,</p><figure class="highlight xl"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs xl"><span class="hljs-function"><span class="hljs-title">ph</span> = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR-></span>e_phoff);<br><span class="hljs-function"><span class="hljs-title">eph</span> = ph + ELFHDR-></span>e_phnum;<br><span class="hljs-keyword">for</span> (; ph < eph; ph ++) {<br> <span class="hljs-function"><span class="hljs-title">readseg</span>(ph-></span><span class="hljs-function"><span class="hljs-title">p_va</span> & 0xFFFFFF, ph-></span><span class="hljs-function"><span class="hljs-title">p_memsz</span>, ph-></span>p_offset);<br>}<br></code></pre></div></td></tr></tbody></table></figure><h2 id="练习5">练习5</h2><p>在kern/debug/kdebug.c的最后有我们要完成的代码,不难写出:</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs cpp"> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print_stackframe</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br> <span class="hljs-keyword">uint32_t</span> ebp=<span class="hljs-built_in">read_ebp</span>(); <span class="hljs-comment">//(1) call read_ebp() to get the value of ebp. the type is (uint32_t)</span><br> <span class="hljs-keyword">uint32_t</span> eip=<span class="hljs-built_in">read_eip</span>(); <span class="hljs-comment">//(2) call read_eip() to get the value of eip. the type is (uint32_t)</span><br> <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i<STACKFRAME_DEPTH&&ebp!=<span class="hljs-number">0</span>;i++){ <span class="hljs-comment">//(3) from 0 .. STACKFRAME_DEPTH</span><br> <span class="hljs-built_in">cprintf</span>(<span class="hljs-string">"ebp:0x%08x eip:0x%08x "</span>,ebp,eip); <span class="hljs-comment">//(3.1)printf value of ebp, eip</span><br> <span class="hljs-keyword">uint32_t</span> *tmp=(<span class="hljs-keyword">uint32_t</span> *)ebp+<span class="hljs-number">2</span>;<br> <span class="hljs-built_in">cprintf</span>(<span class="hljs-string">"arg :0x%08x 0x%08x 0x%08x 0x%08x"</span>,*(tmp+<span class="hljs-number">0</span>),*(tmp+<span class="hljs-number">1</span>),*(tmp+<span class="hljs-number">2</span>),*(tmp+<span class="hljs-number">3</span>)); <span class="hljs-comment">//(3.2)(uint32_t)calling </span><br><br>arguments [<span class="hljs-number">0.</span><span class="hljs-number">.4</span>] = the contents in <span class="hljs-built_in">address</span> (<span class="hljs-keyword">unit32_t</span>)ebp +<span class="hljs-number">2</span> [<span class="hljs-number">0.</span><span class="hljs-number">.4</span>]<br> <span class="hljs-built_in">cprintf</span>(<span class="hljs-string">"\n"</span>); <span class="hljs-comment">//(3.3) cprintf("\n");</span><br> <span class="hljs-built_in">print_debuginfo</span>(eip<span class="hljs-number">-1</span>); <span class="hljs-comment">//(3.4) call print_debuginfo(eip-1) to print the C calling function name and line </span><br><br>number, etc.<br> eip=((<span class="hljs-keyword">uint32_t</span> *)ebp)[<span class="hljs-number">1</span>];<br> ebp=((<span class="hljs-keyword">uint32_t</span> *)ebp)[<span class="hljs-number">0</span>]; <span class="hljs-comment">//(3.5) popup a calling stackframe</span><br> }<br> }<br></code></pre></div></td></tr></tbody></table></figure><p>注意先切换eip,在切换ebp</p><p>结果:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161841018.png" srcset="/img/loading.gif" lazyload></p><h2 id="练习6">练习6</h2><p>直接上图和代码:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204161844164.png" srcset="/img/loading.gif" lazyload></p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml"> <span class="hljs-built_in">int</span> i = <span class="hljs-number">0</span>;<br> extern uintptr_t __vectors<span class="hljs-literal">[]</span>;<br> <span class="hljs-keyword">for</span>(i = <span class="hljs-number">0</span>; i < <span class="hljs-number">255</span>; ++i)<br> {<br><span class="hljs-comment">// vectors 中存储了中断处理程序的入口地址。vectors 定义在 vector.S 文件中,通过一个工具程序 vector.c 生成</span><br> <span class="hljs-constructor">SETGATE(<span class="hljs-params">idt</span>[<span class="hljs-params">i</span>], 0, GD_KTEXT, <span class="hljs-params">__vectors</span>[<span class="hljs-params">i</span>], 0)</span>;<br> <span class="hljs-comment">//在os中,特权级别通常用数字表示,这里的0就是kernel模式</span><br> }<br><span class="hljs-comment">// setgate切换用户模式到内核模式</span><br> <span class="hljs-constructor">SETGATE(<span class="hljs-params">idt</span>[T_SWITCH_TOK], 1, GD_KTEXT, <span class="hljs-params">__vectors</span>[T_SWITCH_TOK], 3)</span>;<br> <span class="hljs-comment">//加载idt </span><br> lidt(&idt_pd);<br></code></pre></div></td></tr></tbody></table></figure><figure class="highlight scss"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs scss">case IRQ_OFFSET + IRQ_TIMER:<br> <br> ticks ++;<br> if (ticks % TICK_NUM == <span class="hljs-number">0</span>) {<br> print_ticks();<br> }<br><br> break;<br> <span class="hljs-comment">//这个没什么意思</span><br></code></pre></div></td></tr></tbody></table></figure><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204171129336.png" srcset="/img/loading.gif" lazyload></p><h2 id="扩展练习">扩展练习</h2><h3 id="challenge-1">challenge 1</h3><p>修改:</p><figure class="highlight awk"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs awk">struct trapframe *switchu2k;<br>struct trapframe switchk2u;<br>........<br><span class="hljs-regexp">//</span> 全局变量<br>struct trapframe switchk2u;<br><span class="hljs-regexp">//</span> ......<br>case T_SWITCH_TOK:<br> <span class="hljs-keyword">if</span> (tf->tf_cs != KERNEL_CS) {<br> <span class="hljs-regexp">//</span> 修改相应段以提升特权级<br> tf->tf_cs = KERNEL_CS;<br> tf->tf_ds = tf->tf_es = KERNEL_DS;<br> tf->tf_eflags &= ~FL_IOPL_MASK;<br> <br> <span class="hljs-regexp">//</span> 计算将要保存新trapFrame的用户栈地址<br> <span class="hljs-regexp">//</span> 数值减<span class="hljs-number">8</span>是因为内核调用中断时CPU没有压入ss和esp<br> switchu2k = (struct trapframe *)(tf->tf_esp - (sizeof(struct trapframe) - <span class="hljs-number">8</span>));<br> <span class="hljs-regexp">//</span> 将修改后的trapFrame写入用户栈(注意当前是内核栈)。注意trapFrame中ss和esp的值不需要写入。<br> memmove(switchu2k, tf, sizeof(struct trapframe) - <span class="hljs-number">8</span>);<br> <span class="hljs-regexp">//</span> 设置弹出esp的值为用户栈的新地址<br> *((uint32_t *)tf - <span class="hljs-number">1</span>) = (uint32_t)switchu2k;<br>}<br><span class="hljs-keyword">break</span>;<br><span class="hljs-regexp">//</span> 全局变量<br>struct trapframe *switchu2k;<br><span class="hljs-regexp">//</span> ......<br>case T_SWITCH_TOU:<br> <span class="hljs-keyword">if</span> (tf->tf_cs != USER_CS) {<br> <span class="hljs-regexp">//</span> switchk2u是之前定义的trapframe,将中断的栈帧赋给临时中断帧<br> switchk2u = *tf;<br><br> switchk2u.tf_cs = USER_CS;<br><br> switchk2u.tf_ds = switchk2u.tf_es = switchk2u.tf_ss = USER_DS;<br> <span class="hljs-regexp">//</span>上面是修改对应的段为user段<br><br> <span class="hljs-regexp">//</span> 数值减<span class="hljs-number">8</span>是因为iret不会弹出ss和esp,所以不需要这<span class="hljs-number">8</span>个字节<br> switchk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - <span class="hljs-number">8</span>;<br><br> <span class="hljs-regexp">//</span> 将eflags中对应的IOPL位置成表示用户态的<span class="hljs-number">3</span><br> switchk2u.tf_eflags |= FL_IOPL_MASK;<br> <span class="hljs-regexp">//</span> 设置中断处理例程结束时pop出的%esp,这样可以用修改后的数据来恢复上下文。<br> *((uint32_t *)tf - <span class="hljs-number">1</span>) = (uint32_t)&switchk2u;<br> }<br> <span class="hljs-regexp">//</span>实质只是通过改变段来改变权级<br><span class="hljs-keyword">break</span>;<br></code></pre></div></td></tr></tbody></table></figure><p>以及:</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs cpp"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">lab1_switch_to_user</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br><br><span class="hljs-function"><span class="hljs-keyword">asm</span> <span class="hljs-title">volatile</span> <span class="hljs-params">(</span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-string">"sub $0x8, %%esp \n"</span></span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-string">"int %0 \n"</span></span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-string">"movl %%ebp, %%esp"</span></span></span><br><span class="hljs-params"><span class="hljs-function"> : </span></span><br><span class="hljs-params"><span class="hljs-function"> : <span class="hljs-string">"i"</span>(T_SWITCH_TOU)</span></span><br><span class="hljs-params"><span class="hljs-function">)</span></span>;<br>}<br><br><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">lab1_switch_to_kernel</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{<br><br><span class="hljs-function"><span class="hljs-keyword">asm</span> <span class="hljs-title">volatile</span> <span class="hljs-params">(</span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-string">"int %0 \n"</span></span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-string">"movl %%ebp, %%esp \n"</span></span></span><br><span class="hljs-params"><span class="hljs-function"> : </span></span><br><span class="hljs-params"><span class="hljs-function"> : <span class="hljs-string">"i"</span>(T_SWITCH_TOK)</span></span><br><span class="hljs-params"><span class="hljs-function">)</span></span>;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>inti.c里有坑,第一个函数需要是void类型</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204162235049.png" srcset="/img/loading.gif" lazyload></p><h3 id="chanllenge-2">chanllenge 2</h3><figure class="highlight xl"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs xl">case IRQ_OFFSET + IRQ_KBD:<br> c = cons_getc();<br> cprintf(<span class="hljs-string">"kbd [%03d] %c\n"</span>, c, c);<br><span class="hljs-comment">//和chanllenge1代码基本相同</span><br> <span class="hljs-keyword">if</span>(c == <span class="hljs-string">'0'</span>)<br> {<br> <span class="hljs-function"><span class="hljs-title">if</span> (tf-></span>tf_cs != KERNEL_CS) {<br> cprintf(<span class="hljs-string">"+++ switch to kernel mode +++\n"</span>);<br> <span class="hljs-function"><span class="hljs-title">tf</span>-></span>tf_cs = KERNEL_CS;<br> <span class="hljs-function"><span class="hljs-title">tf</span>-></span><span class="hljs-function"><span class="hljs-title">tf_ds</span> = tf-></span>tf_es = KERNEL_DS;<br> <span class="hljs-function"><span class="hljs-title">tf</span>-></span>tf_eflags &= ~FL_IOPL_MASK;<br> <span class="hljs-function"><span class="hljs-title">switchu2k</span> = (struct trapframe *)(tf-></span>tf_esp - (sizeof(struct trapframe) - <span class="hljs-number">8</span>));<br> memmove(switchu2k, tf, sizeof(struct trapframe) - <span class="hljs-number">8</span>);<br> *((uint32_t *)tf - <span class="hljs-number">1</span>) = (uint32_t)switchu2k;<br> }<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(c == <span class="hljs-string">'3'</span>)<br> {<br> <span class="hljs-function"><span class="hljs-title">if</span> (tf-></span>tf_cs != USER_CS) {<br> cprintf(<span class="hljs-string">"+++ switch to user mode +++\n"</span>);<br> switchk2u = *tf;<br> switchk2u.tf_cs = USER_CS;<br> switchk2u.tf_ds = switchk2u.tf_es = switchk2u.tf_ss = USER_DS;<br> switchk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - <span class="hljs-number">8</span>;<br> switchk2u.tf_eflags |= FL_IOPL_MASK;<br> *((uint32_t *)tf - <span class="hljs-number">1</span>) = (uint32_t)&switchk2u;<br> }<br> }<br><br> <br> <span class="hljs-comment">/* do nothing */</span><br> break;<br></code></pre></div></td></tr></tbody></table></figure><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204171130119.png" srcset="/img/loading.gif" lazyload></p>]]></content>
<summary type="html"><p>RT</p>
<p><span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.186ex" xmlns="http://www.w3.o</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="ucore" scheme="https://heeler-deer.top/tags/ucore/"/>
</entry>
<entry>
<title>对udisk操作</title>
<link href="https://heeler-deer.top/posts/c4f3f0b4/"/>
<id>https://heeler-deer.top/posts/c4f3f0b4/</id>
<published>2022-04-06T09:15:06.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="前言">前言</h1><p>这几天为了<del>完成导师的任务</del>在封校的苦闷日子中找一点乐趣,想着怎么对自己的u盘进行一些操作,让我能够读取固定位置的数据。</p><p>然后我就<del>苦逼得</del>找了两天。</p><p>其实早就找到了 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="5.778ex" height="1.645ex" role="img" focusable="false" viewBox="0 -705 2554 727"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D446" d="M308 24Q367 24 416 76T466 197Q466 260 414 284Q308 311 278 321T236 341Q176 383 176 462Q176 523 208 573T273 648Q302 673 343 688T407 704H418H425Q521 704 564 640Q565 640 577 653T603 682T623 704Q624 704 627 704T632 705Q645 705 645 698T617 577T585 459T569 456Q549 456 549 465Q549 471 550 475Q550 478 551 494T553 520Q553 554 544 579T526 616T501 641Q465 662 419 662Q362 662 313 616T263 510Q263 480 278 458T319 427Q323 425 389 408T456 390Q490 379 522 342T554 242Q554 216 546 186Q541 164 528 137T492 78T426 18T332 -20Q320 -22 298 -22Q199 -22 144 33L134 44L106 13Q83 -14 78 -18T65 -22Q52 -22 52 -14Q52 -11 110 221Q112 227 130 227H143Q149 221 149 216Q149 214 148 207T144 186T142 153Q144 114 160 87T203 47T255 29T308 24Z"></path></g><g data-mml-node="mi" transform="translate(645,0)"><path data-c="1D436" d="M50 252Q50 367 117 473T286 641T490 704Q580 704 633 653Q642 643 648 636T656 626L657 623Q660 623 684 649Q691 655 699 663T715 679T725 690L740 705H746Q760 705 760 698Q760 694 728 561Q692 422 692 421Q690 416 687 415T669 413H653Q647 419 647 422Q647 423 648 429T650 449T651 481Q651 552 619 605T510 659Q484 659 454 652T382 628T299 572T226 479Q194 422 175 346T156 222Q156 108 232 58Q280 24 350 24Q441 24 512 92T606 240Q610 253 612 255T628 257Q648 257 648 248Q648 243 647 239Q618 132 523 55T319 -22Q206 -22 128 53T50 252Z"></path></g><g data-mml-node="mi" transform="translate(1405,0)"><path data-c="1D446" d="M308 24Q367 24 416 76T466 197Q466 260 414 284Q308 311 278 321T236 341Q176 383 176 462Q176 523 208 573T273 648Q302 673 343 688T407 704H418H425Q521 704 564 640Q565 640 577 653T603 682T623 704Q624 704 627 704T632 705Q645 705 645 698T617 577T585 459T569 456Q549 456 549 465Q549 471 550 475Q550 478 551 494T553 520Q553 554 544 579T526 616T501 641Q465 662 419 662Q362 662 313 616T263 510Q263 480 278 458T319 427Q323 425 389 408T456 390Q490 379 522 342T554 242Q554 216 546 186Q541 164 528 137T492 78T426 18T332 -20Q320 -22 298 -22Q199 -22 144 33L134 44L106 13Q83 -14 78 -18T65 -22Q52 -22 52 -14Q52 -11 110 221Q112 227 130 227H143Q149 221 149 216Q149 214 148 207T144 186T142 153Q144 114 160 87T203 47T255 29T308 24Z"></path></g><g data-mml-node="mi" transform="translate(2050,0)"><path data-c="1D43C" d="M43 1Q26 1 26 10Q26 12 29 24Q34 43 39 45Q42 46 54 46H60Q120 46 136 53Q137 53 138 54Q143 56 149 77T198 273Q210 318 216 344Q286 624 286 626Q284 630 284 631Q274 637 213 637H193Q184 643 189 662Q193 677 195 680T209 683H213Q285 681 359 681Q481 681 487 683H497Q504 676 504 672T501 655T494 639Q491 637 471 637Q440 637 407 634Q393 631 388 623Q381 609 337 432Q326 385 315 341Q245 65 245 59Q245 52 255 50T307 46H339Q345 38 345 37T342 19Q338 6 332 0H316Q279 2 179 2Q143 2 113 2T65 2T43 1Z"></path></g></g></g></svg></mjx-container>这一杀器,问题是我不知道怎么执行scsi命令。</p><p>下面介绍一下最强大的u盘工具: <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.898ex" height="2.034ex" role="img" focusable="false" viewBox="0 -694 3491 899"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z"></path></g><g data-mml-node="mi" transform="translate(469,0)"><path data-c="1D454" d="M311 43Q296 30 267 15T206 0Q143 0 105 45T66 160Q66 265 143 353T314 442Q361 442 401 394L404 398Q406 401 409 404T418 412T431 419T447 422Q461 422 470 413T480 394Q480 379 423 152T363 -80Q345 -134 286 -169T151 -205Q10 -205 10 -137Q10 -111 28 -91T74 -71Q89 -71 102 -80T116 -111Q116 -121 114 -130T107 -144T99 -154T92 -162L90 -164H91Q101 -167 151 -167Q189 -167 211 -155Q234 -144 254 -122T282 -75Q288 -56 298 -13Q311 35 311 43ZM384 328L380 339Q377 350 375 354T369 368T359 382T346 393T328 402T306 405Q262 405 221 352Q191 313 171 233T151 117Q151 38 213 38Q269 38 323 108L331 118L384 328Z"></path></g><g data-mml-node="mn" transform="translate(946,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z"></path></g><g data-mml-node="mi" transform="translate(1446,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2018,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(2379,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2724,0)"><path data-c="1D459" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path></g><g data-mml-node="mi" transform="translate(3022,0)"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z"></path></g></g></g></svg></mjx-container></p><h1 id="sg3_utils">sg3_utils</h1><p>所谓 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.898ex" height="2.034ex" role="img" focusable="false" viewBox="0 -694 3491 899"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z"></path></g><g data-mml-node="mi" transform="translate(469,0)"><path data-c="1D454" d="M311 43Q296 30 267 15T206 0Q143 0 105 45T66 160Q66 265 143 353T314 442Q361 442 401 394L404 398Q406 401 409 404T418 412T431 419T447 422Q461 422 470 413T480 394Q480 379 423 152T363 -80Q345 -134 286 -169T151 -205Q10 -205 10 -137Q10 -111 28 -91T74 -71Q89 -71 102 -80T116 -111Q116 -121 114 -130T107 -144T99 -154T92 -162L90 -164H91Q101 -167 151 -167Q189 -167 211 -155Q234 -144 254 -122T282 -75Q288 -56 298 -13Q311 35 311 43ZM384 328L380 339Q377 350 375 354T369 368T359 382T346 393T328 402T306 405Q262 405 221 352Q191 313 171 233T151 117Q151 38 213 38Q269 38 323 108L331 118L384 328Z"></path></g><g data-mml-node="mn" transform="translate(946,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z"></path></g><g data-mml-node="mi" transform="translate(1446,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2018,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(2379,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2724,0)"><path data-c="1D459" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path></g><g data-mml-node="mi" transform="translate(3022,0)"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z"></path></g></g></g></svg></mjx-container>,实际上是封装好的c函数库,安装好后可以直接在系统内调用相关函数来执行udisk相关操作。<strong>完善支持macos,linux,windows</strong></p><h2 id="安装">安装</h2><p>安装有大坑,至少我在linux上是这样。</p><p>先介绍我的 <strong>环境</strong>:</p><figure class="highlight apache"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs apache"><span class="hljs-attribute">Ubuntu</span>: <span class="hljs-number">21</span>.<span class="hljs-number">20</span><br></code></pre></div></td></tr></tbody></table></figure><p>安装有两种方式,一:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">sudo apt-get install sg3-utils<br></code></pre></div></td></tr></tbody></table></figure><p>我未尝试该方法,该方法可能会出现一些问题。</p><p>另一种是在<a href="http://sg.danny.cz/sg/sg3_utils.html">官网</a>通过源码编译安装,我下载的是<a href="http://sg.danny.cz/sg/p/sg3_utils-1.47.tar.xz">1.47.tar.xz</a>。</p><p>之后的安装方式是这样的:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">sudo ./configure --prefix=/usr --disable-static && make<br><span class="hljs-meta"></span><br><span class="hljs-meta">#</span><span class="bash">之后:</span><br>sudo make install<br></code></pre></div></td></tr></tbody></table></figure><p>这里解释一下,<code>--disable-static</code>会阻止安装时采用依赖库的静态版本(参考<a href="http://blog.chinaunix.net/uid-30221233-id-5556840.html">博文</a>),如果不这样做,可能会在<code>执行命令时</code>产生和我一样的错误:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">error while loading shared libraries: libsgutils2.so.1.47: cannot open shared object file: No such file or directory<br></code></pre></div></td></tr></tbody></table></figure><p>即便采用软链接的方式把<code>libsgutils2.so.2</code>链接到<code>libgutils2.so.147</code>也不行。</p><p>我在这里耽误了好久,最终找到上文中的<a href="http://blog.chinaunix.net/uid-30221233-id-5556840.html">博文</a>才知道是安装是出了问题。<span class="github-emoji"><span>😂</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f602.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><h2 id="使用">使用</h2><p>在我的 <span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="12.622ex" height="1.62ex" role="img" focusable="false" viewBox="0 -694 5579 716"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D448" d="M107 637Q73 637 71 641Q70 643 70 649Q70 673 81 682Q83 683 98 683Q139 681 234 681Q268 681 297 681T342 682T362 682Q378 682 378 672Q378 670 376 658Q371 641 366 638H364Q362 638 359 638T352 638T343 637T334 637Q295 636 284 634T266 623Q265 621 238 518T184 302T154 169Q152 155 152 140Q152 86 183 55T269 24Q336 24 403 69T501 205L552 406Q599 598 599 606Q599 633 535 637Q511 637 511 648Q511 650 513 660Q517 676 519 679T529 683Q532 683 561 682T645 680Q696 680 723 681T752 682Q767 682 767 672Q767 650 759 642Q756 637 737 637Q666 633 648 597Q646 592 598 404Q557 235 548 205Q515 105 433 42T263 -22Q171 -22 116 34T60 167V183Q60 201 115 421Q164 622 164 628Q164 635 107 637Z"></path></g><g data-mml-node="mi" transform="translate(767,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g><g data-mml-node="mi" transform="translate(1196,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1768,0)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2368,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(2729,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mn" transform="translate(3301,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(1278,0)"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1778,0)"></path></g></g></g></svg></mjx-container></span>环境中,要读取u disk指定位置的内容,首先查看u盘名称:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell"><span class="hljs-meta">></span><span class="bash"> df -h</span><br>文件系统 容量 已用 可用 已用% 挂载点<br>tmpfs 1.4G 3.7M 1.4G 1% /run<br>/dev/nvme0n1p8 428G 207G 200G 51% /<br>tmpfs 6.8G 163M 6.7G 3% /dev/shm<br>tmpfs 5.0M 4.0K 5.0M 1% /run/lock<br>/dev/nvme0n1p1 256M 34M 223M 14% /boot/efi<br>tmpfs 1.4G 188K 1.4G 1% /run/user/1000<br>/dev/sda1 30G 112K 30G 1% /media/heeler/UBUNTU 21_0<br></code></pre></div></td></tr></tbody></table></figure><p>我对linux的了解并不深,其中 <code>/dev/sda1</code> 与根目录下的<code>/dev/sg0</code>应为同一个设备,应该是linux对u盘不同功能的区分,实际上还是同一个设备。</p><p>之后我们可以对u disk进行读取操作了:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">❯ sudo sg_read if=/dev/sg0 bs=512 count=2kB mmap=1 time=1<br>[sudo] heeler 的密码: <br>Time for all SCSI READ commands was 0.016853 secs, 60.76 MB/sec<br>Average number of SCSI READ commands per second was 949.39<br>2000+0 records in, SCSI READ commands issued: 16<br></code></pre></div></td></tr></tbody></table></figure><p><code>sg_read</code> 属于 <code>sg3_utils</code>的一个函数,其官方介绍在<a href="https://linux.die.net/man/8/sg_read">网址</a>, <code>if</code>参数指定挂载的文件系统, <code>bs</code>是要读取的每一个块(block,<del>我不知道怎么翻译</del>)的大小,这里是对每一个块读取512字节,<code>count</code> 相当于读取的数据量,这里是读取2kb大小的块,<code>time</code>相当于开启一个计时选项,当然sg_read还有很多参数可选,具体参数请参考官方文档。</p><p>当然,我们不能只是一行行的敲shell命令,那么怎么把命令写在脚本里面呢?</p><p>我首先尝试了写一个1.sh脚本:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">sg_read if=/dev/sg0 bs=512 count=2kB mmap=1 time=1<br></code></pre></div></td></tr></tbody></table></figure><p>然后<code>sudo ./1.sh</code>,会显示commod not found;或者在su-root下<code>sudo ./1.sh</code>显示权限不够,原因在于1.sh要求读取系统层面的文件,而sg_read并没有添加到系统配置里面,所以显示commandnot found或者权限不够,具体原因我还不是很了解。 <span class="github-emoji"><span>🥺</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f97a.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><p>那么我们怎么办呢?</p><p>上 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.382ex" height="2.034ex" role="img" focusable="false" viewBox="0 -694 3263 899"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D443" d="M287 628Q287 635 230 637Q206 637 199 638T192 648Q192 649 194 659Q200 679 203 681T397 683Q587 682 600 680Q664 669 707 631T751 530Q751 453 685 389Q616 321 507 303Q500 302 402 301H307L277 182Q247 66 247 59Q247 55 248 54T255 50T272 48T305 46H336Q342 37 342 35Q342 19 335 5Q330 0 319 0Q316 0 282 1T182 2Q120 2 87 2T51 1Q33 1 33 11Q33 13 36 25Q40 41 44 43T67 46Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628ZM645 554Q645 567 643 575T634 597T609 619T560 635Q553 636 480 637Q463 637 445 637T416 636T404 636Q391 635 386 627Q384 621 367 550T332 412T314 344Q314 342 395 342H407H430Q542 342 590 392Q617 419 631 471T645 554Z"></path></g><g data-mml-node="mi" transform="translate(751,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1241,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(1602,0)"><path data-c="210E" d="M137 683Q138 683 209 688T282 694Q294 694 294 685Q294 674 258 534Q220 386 220 383Q220 381 227 388Q288 442 357 442Q411 442 444 415T478 336Q478 285 440 178T402 50Q403 36 407 31T422 26Q450 26 474 56T513 138Q516 149 519 151T535 153Q555 153 555 145Q555 144 551 130Q535 71 500 33Q466 -10 419 -10H414Q367 -10 346 17T325 74Q325 90 361 192T398 345Q398 404 354 404H349Q266 404 205 306L198 293L164 158Q132 28 127 16Q114 -11 83 -11Q69 -11 59 -2T48 16Q48 30 121 320L195 616Q195 629 188 632T149 637H128Q122 643 122 645T124 664Q129 683 137 683Z"></path></g><g data-mml-node="mi" transform="translate(2178,0)"><path data-c="1D45C" d="M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z"></path></g><g data-mml-node="mi" transform="translate(2663,0)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path></g></g></g></svg></mjx-container></p><p>我写了一个脚本1.py,在 <code>sudo python3 1.py</code>就可以了。下面是py脚本:</p><figure class="highlight python"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs python"><span class="hljs-keyword">import</span> os<br>process=os.popen(<span class="hljs-string">"sg_read if=/dev/sg0 bs=512 count=2kB mmap=1 time=1"</span>)<br>output=process.read()<br>process.close()<br><span class="hljs-built_in">print</span>(output)<br></code></pre></div></td></tr></tbody></table></figure><p>用上python之后,就可以加一些奇技淫巧了。比如添加随机数据,随机读取数据以测量udisk的性能。</p><h1 id="写在最后">写在最后</h1><p>不得不说,从 <span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="1.131ex" height="1.557ex" role="img" focusable="false" viewBox="0 -666 500 688"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path></g></g></g></svg></mjx-container></span> 开始真的痛苦,<del>某人</del>没人指导,没人给方向,前半部分时间我一直在研究一个<a href="https://developer.ibm.com/tutorials/l-scsi-api/">脚本</a>,他通过直接调用内核参数来实现对udisk的操作。我还大致浏览了一些scsi的书籍,比如来自mit的<a href="http://www.mit.edu/afs.new/athena/system/rhlinux/redhat-6.2-docs/HOWTOS/other-formats/pdf/SCSI-Programming-HOWTO.pdf">scsi</a>,结果<del>屁用没有</del>成功提高了我对scsi的理解。这也是我写出这篇博客的动力,帮助人们认识到<mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.464ex" xmlns="http://www.w3.org/2000/svg" width="7.898ex" height="2.034ex" role="img" focusable="false" viewBox="0 -694 3491 899"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z"></path></g><g data-mml-node="mi" transform="translate(469,0)"><path data-c="1D454" d="M311 43Q296 30 267 15T206 0Q143 0 105 45T66 160Q66 265 143 353T314 442Q361 442 401 394L404 398Q406 401 409 404T418 412T431 419T447 422Q461 422 470 413T480 394Q480 379 423 152T363 -80Q345 -134 286 -169T151 -205Q10 -205 10 -137Q10 -111 28 -91T74 -71Q89 -71 102 -80T116 -111Q116 -121 114 -130T107 -144T99 -154T92 -162L90 -164H91Q101 -167 151 -167Q189 -167 211 -155Q234 -144 254 -122T282 -75Q288 -56 298 -13Q311 35 311 43ZM384 328L380 339Q377 350 375 354T369 368T359 382T346 393T328 402T306 405Q262 405 221 352Q191 313 171 233T151 117Q151 38 213 38Q269 38 323 108L331 118L384 328Z"></path></g><g data-mml-node="mn" transform="translate(946,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z"></path></g><g data-mml-node="mi" transform="translate(1446,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2018,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(2379,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2724,0)"><path data-c="1D459" d="M117 59Q117 26 142 26Q179 26 205 131Q211 151 215 152Q217 153 225 153H229Q238 153 241 153T246 151T248 144Q247 138 245 128T234 90T214 43T183 6T137 -11Q101 -11 70 11T38 85Q38 97 39 102L104 360Q167 615 167 623Q167 626 166 628T162 632T157 634T149 635T141 636T132 637T122 637Q112 637 109 637T101 638T95 641T94 647Q94 649 96 661Q101 680 107 682T179 688Q194 689 213 690T243 693T254 694Q266 694 266 686Q266 675 193 386T118 83Q118 81 118 75T117 65V59Z"></path></g><g data-mml-node="mi" transform="translate(3022,0)"><path data-c="1D460" d="M131 289Q131 321 147 354T203 415T300 442Q362 442 390 415T419 355Q419 323 402 308T364 292Q351 292 340 300T328 326Q328 342 337 354T354 372T367 378Q368 378 368 379Q368 382 361 388T336 399T297 405Q249 405 227 379T204 326Q204 301 223 291T278 274T330 259Q396 230 396 163Q396 135 385 107T352 51T289 7T195 -10Q118 -10 86 19T53 87Q53 126 74 143T118 160Q133 160 146 151T160 120Q160 94 142 76T111 58Q109 57 108 57T107 55Q108 52 115 47T146 34T201 27Q237 27 263 38T301 66T318 97T323 122Q323 150 302 164T254 181T195 196T148 231Q131 256 131 289Z"></path></g></g></g></svg></mjx-container> 这个强大的工具。 <span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="7.649ex" height="1.645ex" role="img" focusable="false" viewBox="0 -705 3381 727"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43A" d="M50 252Q50 367 117 473T286 641T490 704Q580 704 633 653Q642 643 648 636T656 626L657 623Q660 623 684 649Q691 655 699 663T715 679T725 690L740 705H746Q760 705 760 698Q760 694 728 561Q692 422 692 421Q690 416 687 415T669 413H653Q647 419 647 422Q647 423 648 429T650 449T651 481Q651 552 619 605T510 659Q492 659 471 656T418 643T357 615T294 567T236 496T189 394T158 260Q156 242 156 221Q156 173 170 136T206 79T256 45T308 28T353 24Q407 24 452 47T514 106Q517 114 529 161T541 214Q541 222 528 224T468 227H431Q425 233 425 235T427 254Q431 267 437 273H454Q494 271 594 271Q634 271 659 271T695 272T707 272Q721 272 721 263Q721 261 719 249Q714 230 709 228Q706 227 694 227Q674 227 653 224Q646 221 643 215T629 164Q620 131 614 108Q589 6 586 3Q584 1 581 1Q571 1 553 21T530 52Q530 53 528 52T522 47Q448 -22 322 -22Q201 -22 126 55T50 252Z"></path></g><g data-mml-node="mi" transform="translate(786,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1131,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(1492,0)"><path data-c="1D43B" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 219 683Q260 681 355 681Q389 681 418 681T463 682T483 682Q499 682 499 672Q499 670 497 658Q492 641 487 638H485Q483 638 480 638T473 638T464 637T455 637Q416 636 405 634T387 623Q384 619 355 500Q348 474 340 442T328 395L324 380Q324 378 469 378H614L615 381Q615 384 646 504Q674 619 674 627T617 637Q594 637 587 639T580 648Q580 650 582 660Q586 677 588 679T604 682Q609 682 646 681T740 680Q802 680 835 681T871 682Q888 682 888 672Q888 645 876 638H874Q872 638 869 638T862 638T853 637T844 637Q805 636 794 634T776 623Q773 618 704 340T634 58Q634 51 638 51Q646 48 692 46H723Q729 38 729 37T726 19Q722 6 716 0H701Q664 2 567 2Q533 2 504 2T458 2T437 1Q420 1 420 10Q420 15 423 24Q428 43 433 45Q437 46 448 46H454Q481 46 514 49Q520 50 522 50T528 55T534 64T540 82T547 110T558 153Q565 181 569 198Q602 330 602 331T457 332H312L279 197Q245 63 245 58Q245 51 253 49T303 46H334Q340 38 340 37T337 19Q333 6 327 0H312Q275 2 178 2Q144 2 115 2T69 2T48 1Q31 1 31 10Q31 12 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g><g data-mml-node="mi" transform="translate(2380,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2952,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g></g></g></svg></mjx-container></span>也有一个<a href="https://github.com/gostor/gotgt">go</a>写的框架,但现在还没有一个较完善的功能。总之,对udisk进行操作的话,我还是建议使用sg3_utils这个完善、强大的工具。</p><h1 id="参考链接">参考链接</h1><p><a href="http://sg.danny.cz/sg/sg3_utils.html">sg3_utils</a></p><p><a href="http://blog.chinaunix.net/uid-30221233-id-5556840.html">安装博文</a></p><p><a href="https://linux.die.net/man/8/sg_read">sg_read网址</a></p><p><a href="https://linux.die.net/man/8/sg3_utils">sg3_utils汇总工具网址</a></p><p><a href="https://developer.ibm.com/tutorials/l-scsi-api/">使用c调用内核参数的linux下脚本</a></p><p><a href="https://github.com/gostor/gotgt">go写的scsi框架,目前尚不完善</a></p>]]></content>
<summary type="html"><h1 id="前言">前言</h1>
<p>这几天为了<del>完成导师的任务</del>在封校的苦闷日子中找一点乐趣,想着怎么对自己的u盘进行一些操作,让我能够读取固定位置的数据。</p>
<p>然后我就<del>苦逼得</del>找了两天。</p>
<p>其实早就找到了 <</summary>
<category term="瞎搞" scheme="https://heeler-deer.top/categories/%E7%9E%8E%E6%90%9E/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
</entry>
<entry>
<title>计算机系统课程作业</title>
<link href="https://heeler-deer.top/posts/e47a3954/"/>
<id>https://heeler-deer.top/posts/e47a3954/</id>
<published>2022-04-04T07:45:30.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="小班讨论">小班讨论</h1><p>这是本人自己做的小班讨论的题目,放在了 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="7.649ex" height="1.645ex" role="img" focusable="false" viewBox="0 -705 3381 727"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D43A" d="M50 252Q50 367 117 473T286 641T490 704Q580 704 633 653Q642 643 648 636T656 626L657 623Q660 623 684 649Q691 655 699 663T715 679T725 690L740 705H746Q760 705 760 698Q760 694 728 561Q692 422 692 421Q690 416 687 415T669 413H653Q647 419 647 422Q647 423 648 429T650 449T651 481Q651 552 619 605T510 659Q492 659 471 656T418 643T357 615T294 567T236 496T189 394T158 260Q156 242 156 221Q156 173 170 136T206 79T256 45T308 28T353 24Q407 24 452 47T514 106Q517 114 529 161T541 214Q541 222 528 224T468 227H431Q425 233 425 235T427 254Q431 267 437 273H454Q494 271 594 271Q634 271 659 271T695 272T707 272Q721 272 721 263Q721 261 719 249Q714 230 709 228Q706 227 694 227Q674 227 653 224Q646 221 643 215T629 164Q620 131 614 108Q589 6 586 3Q584 1 581 1Q571 1 553 21T530 52Q530 53 528 52T522 47Q448 -22 322 -22Q201 -22 126 55T50 252Z"></path></g><g data-mml-node="mi" transform="translate(786,0)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(1131,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mi" transform="translate(1492,0)"><path data-c="1D43B" d="M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 219 683Q260 681 355 681Q389 681 418 681T463 682T483 682Q499 682 499 672Q499 670 497 658Q492 641 487 638H485Q483 638 480 638T473 638T464 637T455 637Q416 636 405 634T387 623Q384 619 355 500Q348 474 340 442T328 395L324 380Q324 378 469 378H614L615 381Q615 384 646 504Q674 619 674 627T617 637Q594 637 587 639T580 648Q580 650 582 660Q586 677 588 679T604 682Q609 682 646 681T740 680Q802 680 835 681T871 682Q888 682 888 672Q888 645 876 638H874Q872 638 869 638T862 638T853 637T844 637Q805 636 794 634T776 623Q773 618 704 340T634 58Q634 51 638 51Q646 48 692 46H723Q729 38 729 37T726 19Q722 6 716 0H701Q664 2 567 2Q533 2 504 2T458 2T437 1Q420 1 420 10Q420 15 423 24Q428 43 433 45Q437 46 448 46H454Q481 46 514 49Q520 50 522 50T528 55T534 64T540 82T547 110T558 153Q565 181 569 198Q602 330 602 331T457 332H312L279 197Q245 63 245 58Q245 51 253 49T303 46H334Q340 38 340 37T337 19Q333 6 327 0H312Q275 2 178 2Q144 2 115 2T69 2T48 1Q31 1 31 10Q31 12 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z"></path></g><g data-mml-node="mi" transform="translate(2380,0)"><path data-c="1D462" d="M21 287Q21 295 30 318T55 370T99 420T158 442Q204 442 227 417T250 358Q250 340 216 246T182 105Q182 62 196 45T238 27T291 44T328 78L339 95Q341 99 377 247Q407 367 413 387T427 416Q444 431 463 431Q480 431 488 421T496 402L420 84Q419 79 419 68Q419 43 426 35T447 26Q469 29 482 57T512 145Q514 153 532 153Q551 153 551 144Q550 139 549 130T540 98T523 55T498 17T462 -8Q454 -10 438 -10Q372 -10 347 46Q345 45 336 36T318 21T296 6T267 -6T233 -11Q189 -11 155 7Q103 38 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mi" transform="translate(2952,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z"></path></g></g></g></svg></mjx-container>,里面还包含有部分操作系统导论的代码。</p><p>其中第几次小班讨论以英文字母区分,如第一次就是first.</p><p>没有传的就是我没做的</p><p><a href="https://github.com/heeler-deer/absorbing/tree/main/cs-disscussion">GitHub</a></p><h1 id="课程作业">课程作业</h1><p>第一次课程作业网上容易找到答案,我就不放了。</p><h2 id="第二次课程作业">第二次课程作业:</h2><p>简单的放点题目:</p><p><strong>第一题</strong></p><p>有如下c语言程序,其中的H和J定义为一个常数。</p><figure class="highlight c++"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c++"><span class="hljs-meta"># <span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"stdio.h"</span></span><br><br><span class="hljs-meta"># <span class="hljs-meta-keyword">define</span> H ? <span class="hljs-comment">//定义常数H</span></span><br><br><span class="hljs-meta"># <span class="hljs-meta-keyword">define</span> J ? <span class="hljs-comment">//定义常数J</span></span><br><br><br><span class="hljs-keyword">int</span> array1[H][J]; <br><br><span class="hljs-keyword">int</span> array2[J][H]; <br><br><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">f</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{<br><br>array1[x][y] = x+<span class="hljs-number">2</span>*y;<br><br>array2[y][x]=y-x*x;<br><br>}<br><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">( )</span></span><br><span class="hljs-function"></span><br><span class="hljs-function"></span>{<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br><br>}<br></code></pre></div></td></tr></tbody></table></figure><p>我的解答:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs bash">一、<br>H=37,J=16<br>pushl %ebp <br>前两行压程序栈<br><br>movl %esp,%ebp<br><br>push %ebx <br>压 f 函数栈<br><br>movl 8(%ebp), %ecx <br>赋值 x<br><br>movl 12(%ebp), %edx <br>赋值 y<br><br>movl 12(%ebp), %eax <br>赋值 y<br><br>addl %eax, %eax <br>eax 自增为 2 倍(2y)<br><br>addl 8(%ebp), %eax <br>eax=eax+ecx x+2*y<br><br>sall <span class="hljs-variable">$4</span>, %ecx <br>ecx 的值左移 4 位 x*16<br><br>leal (%ecx,%edx), %edx <br>把 ecx+edx 的地址给 edx x*16+y 即 x 的系数 J=16<br><br>movl %eax, array1(,%edx,4) <br>把 eax 的值给 array1 的 edx* 4 位的地方 4*(x* 16+y)的地方=x+2* y,即 array1[x][y]=x+2*y<br><br>movl 12(%ebp), %edx <br>赋值 y<br><br>movl 8(%ebp), %ebx <br>赋值 x<br><br>movl 8(%ebp), %eax <br>赋值 x<br><br>imull 8(%ebp), %eax <br>eax=eax* eax x*x<br><br>movl 12(%ebp), %ecx <br>ecx=edx ecx 处=y<br><br>subl %eax, %ecx <br>ecx=ecx-eax y-x*x<br><br>movl %edx, %eax <br>eax=edx eax 处=y<br><br>sall <span class="hljs-variable">$3</span>, %eax <br>eax < < 3 相当于y < < 3 3 即是 J 的值<br><br>addl %edx, %eax <br>eax=eax+edx y< <3+y<br><br>sall <span class="hljs-variable">$2</span>, %eax <br>eax< <2 (y< <3+y)< <2<br><br>addl %edx, %eax <br>eax=edx+eax (y< <3+y)< <2+y<br><br>addl %ebx, %eax <br>eax=eax+ebx (y< <3+y)< <2+y+x 即 y 的系数 H=(8+1)*4+1=37<br><br>movl %ecx, array2(,%eax,4) <br>把 array2 的 4* eax 的地方赋值为 ecx 即 array2 的 4*eax 的地方=y-x *x 即 array2[x][y]=y-x*x<br><br>popl %ebx <br>出函数栈<br><br>popl %ebp <br>出栈<br><br>ret <br>结束程序<br></code></pre></div></td></tr></tbody></table></figure><p><strong>第二题</strong></p><p>如下为一个c语言程序中的函数及其在32位系统下编译得到的汇编语言程序代码,请详细说明每条汇编语句的意义,并将这个函数补充完整。</p><p>我的解答:</p><figure class="highlight c++"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c++">二、<br><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">aprod</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a[], <span class="hljs-keyword">int</span> n)</span> </span>{<br><br><span class="hljs-keyword">int</span> i, x, y, z;<br><br><span class="hljs-keyword">int</span> r = <span class="hljs-number">1</span>;<br><br><span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; ( i< n<span class="hljs-number">-2</span> ); ( i+=<span class="hljs-number">3</span> )) {<br><br>( x=a[i] );<br><br>( y=a[i+<span class="hljs-number">1</span>] );<br><br>( z=a[i+<span class="hljs-number">2</span>] );<br><br>( r=r*x*y*z* );<br><br> }<br><br> <span class="hljs-keyword">for</span> (; i < n; i++)<br><br> ( r=a[i]*r );<br><br> <span class="hljs-keyword">return</span> r;<br><br>}<br></code></pre></div></td></tr></tbody></table></figure><figure class="highlight bash"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs bash">汇编分析:<br><br>aprod:<br><br>pushl %ebp //前两行压栈<br><br>movl %esp, %ebp //栈帧<br><br>subl <span class="hljs-variable">$32</span>, %esp //esp-32<br><br>movl <span class="hljs-variable">$1</span>, -20(%ebp) //ebp小20的位置放1 r=1<br><br>movl <span class="hljs-variable">$0</span>, -4(%ebp) //ebp小4的位置放0 i=0<br><br>jmp.L2 //无条件跳转到.L2<br><br>.L3:<br><br>movl -4(%ebp), %eax //eax=0=i<br><br>sall <span class="hljs-variable">$2</span>, %eax //eax=0*4=0<br><br>addl 8(%ebp), %eax //eax加上ebp大8的位置,即eax+=a[]<br><br>movl (%eax), %eax //eax=a[i]<br><br>movl %eax, -8(%ebp) //ebp小8的地方赋值为eax x=a[i]<br> <br>movl -4(%ebp), %eax //eax=i=0<br><br>addl <span class="hljs-variable">$1</span>, %eax //eax=i+1=1,<br><br>sall <span class="hljs-variable">$2</span>, %eax //eax=4<br><br>addl 8(%ebp), %eax //eax加上ebp大8的位置 eax=4+a[]<br><br>movl (%eax), %eax //eax=a[i+1]<br><br>movl %eax, -12(%ebp) //ebp小12的位置变为eax y=a[i+1]<br><br>movl -4(%ebp), %eax //eax=ebp小4的位置 eax=i=0<br><br>addl <span class="hljs-variable">$2</span>, %eax //eax+=2 eax=2<br><br>sall <span class="hljs-variable">$2</span>, %eax //eax*=4 eax=8<br><br>addl 8(%ebp), %eax //eax+ebp大8的位置 eax=8+a[]<br><br>movl (%eax), %eax //eax=a[i+2]<br><br>movl %eax, -16(%ebp) //ebp小16的位置放eax z=eax=a[i+2]<br><br>movl -20(%ebp), %eax //eax=1=r<br><br>imull -8(%ebp), %eax //eax*ebp小8处的位置的值 eax=r *x<br><br>imull -12(%ebp), %eax //eax*ebp小12处的位置的值 eax=r *x *y<br><br>imull -16(%ebp), %eax //eax*ebp小16处的位置的值 eax=r *x *y *z<br><br>movl %eax, -20(%ebp) //ebp小20处的位置的值变为eax r=eax<br><br>addl <span class="hljs-variable">$3</span>, -4(%ebp) ebp小4处的位置的值加三 i=i+3<br><br>.L2:<br><br>movl 12(%ebp), %eax //eax被赋值为ebp大12的位置的值 eax=n,<br><br>subl <span class="hljs-variable">$2</span>, %eax //eax-2 eax=n-2<br><br>cmpl -4(%ebp), %eax //比较eax和ebp小4处的值谁大,小于跳到L3,大于等于跳到L4 即比较i和n-2的大小,i>n-2跳转到L3<br><br>jg.L3 <br><br>jmp.L4<br><br>.L5:<br><br>movl -4(%ebp), %eax //eax=0=i<br><br>sall <span class="hljs-variable">$2</span>, %eax //eax*4<br><br>addl 8(%ebp), %eax //eax+大于ebp8的位置的值 即eax=0+a[]<br><br>movl (%eax), %eax //eax=a[i]<br><br>movl -20(%ebp), %edx //edx=1=r <br><br>imull %edx, %eax //eax*=edx 即eax=a[i]*r<br><br>movl %eax, -20(%ebp) //ebp小20处的位置的值等于eax r=eax<br><br>addl <span class="hljs-variable">$1</span>, -4(%ebp) //ebp小4处的位置的值+=1 i+=1<br><br>.L4:<br><br>movl -4(%ebp), %eax //eax=0<br><br>cmpl 12(%ebp), %eax //比较eax和比ebp大12处的位置的值,小于则跳转到L5<br><br>jl.L5<br><br>movl -20(%ebp), %eax //eax=ebp小20处的位置的值<br><br>leave //退出<br><br>ret <br></code></pre></div></td></tr></tbody></table></figure><p><strong>第三题</strong></p><p>有如下C语言程序及在Ubuntu32位系统下用gcc编译而得到的汇编代码,请详细解释每一条汇编指令的意义并将c语言程序补充完整。</p><p>我的解答:</p><figure class="highlight c++"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c++">三、<br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><br><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">frac</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a)</span></span><br><span class="hljs-function"></span><br><span class="hljs-function"></span>{<br><br><span class="hljs-keyword">if</span>(a<<span class="hljs-number">2</span>) <span class="hljs-keyword">return</span> a*a;<br><br><span class="hljs-keyword">return</span> <span class="hljs-built_in">frac</span>(a<span class="hljs-number">-2</span>)+a;<br><br>}<br><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sum</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a,<span class="hljs-keyword">int</span> b)</span></span><br><span class="hljs-function"></span><br><span class="hljs-function"></span>{<br><br><span class="hljs-keyword">int</span> c=<span class="hljs-built_in">frac</span>(a+b);<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">2</span>*c+b;<br><br>}<br><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span><br><span class="hljs-function"></span>{<br><br><span class="hljs-keyword">int</span> i=<span class="hljs-number">10</span>,j=<span class="hljs-number">6</span>;<br><br><span class="hljs-keyword">int</span> k=<span class="hljs-built_in">sum</span>(j-i,i++);<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br><br>}<br></code></pre></div></td></tr></tbody></table></figure><figure class="highlight bash"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs bash">汇编代码:<br>frac:<br><br><br>pushl %ebp //压栈<br>movl %esp, %ebp //栈帧<br>subl <span class="hljs-variable">$24</span>, %esp //esp-24,开辟空间<br>cmpl <span class="hljs-variable">$1</span>, 8(%ebp) //比较1和a的大小,a>1则跳到L2<br>jg .L2<br><br>movl 8(%ebp), %eax //eax=a<br><br>imull 8(%ebp), %eax //eax*=eax,eax=a*a<br><br>jmp .L3 //无条件跳转到L3<br><br>.L2:<br><br>movl 8(%ebp), %eax //eax=a<br><br>subl <span class="hljs-variable">$2</span>, %eax //eax-=2 eax=a-2<br><br>movl %eax, (%esp) //esp的位置=eax=a-2<br><br>call frac //调用frac,此时由于esp的位置是a-2,因此相当于frac(a-2)<br><br>addl 8(%ebp), %eax //eax+=a,即eax=frac(a-2)+a<br><br>.L3:<br><br>leave //退出<br> <br>ret<br><br>sum:<br><br>pushl %ebp //压栈<br><br>movl %esp, %ebp //栈帧<br><br>subl <span class="hljs-variable">$40</span>, %esp //esp-40开辟空间<br><br>movl 12(%ebp), %eax //eax=b<br><br>movl 8(%ebp), %edx //edx=a<br><br>addl %edx, %eax //eax+=edx,eax=b+a<br><br>movl %eax, (%esp) //eax给到esp<br><br>call frac //调用frac函数,同上面的那个frac,相当于frac(a+b)<br><br>movl %eax, -12(%ebp) //c=frac(a+b)<br><br>movl -12(%ebp), %eax //eax=c<br><br>addl %eax, %eax //eax+=eax,eax=2*c<br><br>addl 12(%ebp), %eax //eax+=b,eax=2*c+b<br><br>leave<br><br>ret<br><br>main:<br><br>pushl %ebp //压栈<br><br>movl %esp, %ebp //栈帧<br><br>andl $-16, %esp //esp和-16与运算<br><br>subl <span class="hljs-variable">$32</span>, %esp //esp-32开辟空间<br><br>movl <span class="hljs-variable">$10</span>, 20(%esp) //i=10<br><br>movl <span class="hljs-variable">$6</span>, 24(%esp) //j=6<br><br>movl 20(%esp), %eax //eax=10=i<br><br>movl 24(%esp), %edx //edx=6=j<br><br>subl %eax, %edx //edx=-4<br><br>movl 20(%esp), %eax //eax=10<br><br>addl <span class="hljs-variable">$1</span>, 20(%esp) //i=11<br><br>movl %edx, 4(%esp) //esp大于4处=-4<br><br>movl %eax, (%esp) //eax给到esp=10<br><br>call sum //调用sum,sum函数需要两个参数,这两个参数在上面,也就是sum(j-i,i++)<br><br>movl %eax, 28(%esp) //esp大于28处=10,即k=eax=sum(j-i,i++)<br><br>movl <span class="hljs-variable">$0</span>, %eax //eax=0<br><br>leave //退出<br><br>ret<br></code></pre></div></td></tr></tbody></table></figure><h2 id="第三次课程作业">第三次课程作业:</h2><p>不是很想做硬件。。。</p><h2 id="第四次">第四次</h2><p>课本有答案</p>]]></content>
<summary type="html"><h1 id="小班讨论">小班讨论</h1>
<p>这是本人自己做的小班讨论的题目,放在了 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://w</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
</entry>
<entry>
<title>tools-tcp</title>
<link href="https://heeler-deer.top/posts/e142a365/"/>
<id>https://heeler-deer.top/posts/e142a365/</id>
<published>2022-02-25T08:06:04.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="tools-tcpip">tools-tcp/ip</h1><p>之前阅读<a href="https://juejin.cn/book/6844733788681928712/section/6844733788795174920">掘金小册</a>时一直没实战,这里就补一下</p><h2 id="tcpdump">tcpdump</h2><p>参考网站: <a href="https://www.cnblogs.com/chyingp/p/linux-command-tcpdump.html">博客园</a></p><p>默认情况下tcpdump抓第一个网卡上的数据包</p><p>监听特定网卡使用-i参数</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">tcpdump -i wlo1<br></code></pre></div></td></tr></tbody></table></figure><p>监听特定本机和特定ip的通信使用host参数:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">tcpdump host 111.111.11.11<br></code></pre></div></td></tr></tbody></table></figure><p>监听来源/目标地址通信:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">tcpdump src host 111.111.11.11<br>tcpdump dst host 111.111.11.11<br></code></pre></div></td></tr></tbody></table></figure><p>监听特定端口:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">tcpdump port 3000<br></code></pre></div></td></tr></tbody></table></figure><p>可以指定tcp/udp</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">tcpdump tcp<br></code></pre></div></td></tr></tbody></table></figure><p>监听特定主机之间的通信(需要有权限)</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">tcpdump ip host 210.27.48.1 and 210.27.48.2<br></code></pre></div></td></tr></tbody></table></figure><p>稍微详细点的例子</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs powershell">tcpdump tcp <span class="hljs-literal">-i</span> eth1 <span class="hljs-literal">-t</span> <span class="hljs-literal">-s</span> <span class="hljs-number">0</span> <span class="hljs-literal">-c</span> <span class="hljs-number">100</span> and dst port ! <span class="hljs-number">22</span> and src net <span class="hljs-number">192.168</span>.<span class="hljs-number">1.0</span>/<span class="hljs-number">24</span> <span class="hljs-literal">-w</span> ./target.cap<br></code></pre></div></td></tr></tbody></table></figure><blockquote><p>(1)tcp: ip icmp arp rarp 和tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型(2)-i eth1 : 只抓经过接口eth1的包 (3)-t : 不显示时间戳 (4)-s 0 :抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包 (5)-c100 : 只抓取100个数据包 (6)dst port ! 22 : 不抓取目标端口是22的数据包(7)src net 192.168.1.0/24 : 数据包的源网络地址为192.168.1.0/24 (8)-w./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析</p></blockquote><h2 id="strace">strace</h2><p>参考网站: <a href="https://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html">博客园</a></p><p>strace用来跟踪进程执行时的系统调用以及所接收的信号,如:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">strace cat /dev/null <br>execve("/usr/bin/cat", ["cat", "/dev/null"], 0x7ffc3650b2a8 /* 80 vars */) = 0<br>brk(NULL) = 0x560885cd5000<br>arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd61de71d0) = -1 EINVAL (无效的参数)<br>mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8cb41e5000<br>access("/etc/ld.so.preload", R_OK) = -1 ENOENT (没有那个文件或目录)<br>openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3<br>newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=132945, ...}, AT_EMPTY_PATH) = 0<br>mmap(NULL, 132945, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8cb41c4000<br>close(3) = 0<br></code></pre></div></td></tr></tbody></table></figure><p>每一行都是一个系统调用</p><p>strace的参数:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">-c 统计每一系统调用的所执行的时间,次数和出错的次数等. <br>-d 输出strace关于标准错误的调试信息. <br>-f 跟踪由fork调用所产生的子进程. <br>-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. <br>-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. <br>-r 打印出相对时间关于,,每一个系统调用. <br>-t 在输出中的每一行前加上时间信息. <br>-e trace=set <br>只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all. <br>-e trace=file <br>只跟踪有关文件操作的系统调用. <br>-e trace=process <br>只跟踪有关进程控制的系统调用. <br>-e trace=network <br>跟踪与网络有关的所有系统调用. <br>-e strace=signal <br>跟踪所有与系统信号有关的 系统调用 <br>-e trace=ipc <br>跟踪所有与进程通讯有关的系统调用 <br>-o filename <br>将strace的输出写入文件filename <br>-p pid <br>跟踪指定的进程pid. <br>-u username <br>以username 的UID和GID执行被跟踪的命令<br></code></pre></div></td></tr></tbody></table></figure><p>这个佬的博客写的很详细,案例也不错,建议看看。</p><p>strace给我的感觉是如果不加参数过滤一些信息,给出的信息实在太多了。</p><p>如在我的电脑上<code>strace -o 1.txt pkill goldendict</code>,strace就给出了3287行的信息。。。如果加上参数-etrace=process,那么就只有4行:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">execve("/usr/bin/pkill", ["pkill", "goldendict"], 0x7ffc17024708 /* 83 vars */) = 0<br>kill(340891, SIGTERM) = 0<br>exit_group(0) = ?<br>+++ exited with 0 +++<br></code></pre></div></td></tr></tbody></table></figure><p>我后来又试了试了,<code>sudo strace -e trace=close -f -d -uheeler -o 1.txt pkill goldendict</code>,发现kill这个goldendict的调用的close是真多<span class="github-emoji"><span>😃</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f603.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><h2 id="packetdrill">packetdrill</h2><p>安装:<a href="https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fgoogle%2Fpacketdrill">github</a></p><figure class="highlight bash"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs bash"><span class="hljs-built_in">cd</span> gtests/net/packetdrill<br>sudo apt-get install -y bison flex<br></code></pre></div></td></tr></tbody></table></figure><p>为避免 offload 机制对包大小的影响,修改 netdev.c 注释掉set_device_offload_flags 函数所有内容</p><figure class="highlight bash"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs bash">./configure<br></code></pre></div></td></tr></tbody></table></figure><p>修改 Makefile,去掉第一行的末尾的 -static 执行 make 命令编译可以在目录下尝试packetdrill是否正常生成 加入环境变量:</p><figure class="highlight awk"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs awk">sudo vim <span class="hljs-regexp">/etc/</span>profile<br></code></pre></div></td></tr></tbody></table></figure><p>加入你的路径即可。之后任意打开一个命令行。<code>packetdrill</code>查看是否成功由于packetdrill需要sudo权限,因此需要更改/.zshrc(我用的zsh解释器),在里面加入</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">alias sudo='sudo env PATH="$PATH"'<br></code></pre></div></td></tr></tbody></table></figure><p>之后保存, <code>source /.zshrc</code> 即可</p><p>packetdrill实际上方便了程序员以确定的时间安排系统调用。他可以执行系统调用函数、把数据包注入到内核协议栈,并且支持py、shell,</p><p>来看一个张师傅给出的简单的例子:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs shell">0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3<br>//在第0秒创建一个socket<br>+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0<br>+0 bind(3, ..., ...) = 0<br>+0 listen(3, 1) = 0<br><br>//TCP three-way handshake<br>+0 < S 0:0(0) win 4000 <mss 1000><br>//<表示输入数据包<br>+0 > S. 0:0(0) ack 1 <...><br><span class="hljs-meta">//></span><span class="bash">表示预期协议栈响应的包</span><br>+.1 < . 1:1(0) ack 1 win 1000<br><br>+0 accept(3, ..., ...) = 4<br>+0 write(4, ..., 10) = 10<br>+0 > P. 1:11(10) ack 1<br>+.1 < . 1:1(0) ack 6 win 1000<br></code></pre></div></td></tr></tbody></table></figure><p>上述代码可以通过tcpdump抓到8080端口的包</p><p>packetdrill实际上是通过创建一个虚拟网卡来模拟协议的执行。</p><p>其他内容建议参考: <a href="https://developpaper.com/packetdrill-a-powerful-tool-for-testing-tcp-stack-behavior/">developpaper</a></p>]]></content>
<summary type="html"><h1 id="tools-tcpip">tools-tcp/ip</h1>
<p>之前阅读<a href="https://juejin.cn/book/6844733788681928712/section/6844733788795174920">掘金小册</a>时一直没实</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
</entry>
<entry>
<title>os</title>
<link href="https://heeler-deer.top/posts/6ab04511/"/>
<id>https://heeler-deer.top/posts/6ab04511/</id>
<published>2022-02-24T11:41:45.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="知识补全计划">知识补全计划</h1><p>目前打算按以下顺序补完: <a href="https://zh.u1lib.org/book/16404075/f41379">操作系统:精髓与设计原理</a></p><p><a href="https://zh.u1lib.org/book/16895034/121667">x86汇编</a></p><p><a href="https://pdos.csail.mit.edu/6.828/2011/">mit6.828</a></p><p><a href="https://zh.u1lib.org/book/5645657/616c8e">深入理解linux内核</a></p><p><a href="https://zh.u1lib.org/book/16403051/18a092">x86/x64体系i探索以及编程</a></p><p><strong>相关网站:</strong></p><p><a href="https://wiki.osdev.org/Main_Page">osdev main page</a></p><p><a href="https://forum.osdev.org/">osdev index page</a></p><h1 id="操作系统精髓与设计原理">操作系统:精髓与设计原理</h1><p>由于本人已经学过其他教材讲解的操作系统,这里仅记录那些我认为重要的点,并且仅记录容易记录的、整体性的知识,细枝末节的知识就算了。</p><p>作者认为的与操作系统有关的各种知识分布图:</p><pre><code class=" mermaid">flowchart LR j([进程描述和控制]) d([调度]) n([内存管理]) b([并发]) i([I/O和文件管理]) q([嵌入式]) a([安全]) f([分布式]) j<-->d j<-->b n<-.->d n<-.->b n<-.->i n<-.->q n<-.->d d<-->i b<-.->a b<-->f i<-.->a q<-.->a a<-.->f</code></pre><p>相关网站:</p><p><a href="http://williamstallings.com/OperatingSystems/">web</a></p><p><a href="https://www.cnblogs.com/huyoo/p/14773825.html">复习题答案</a></p><p><a href="https://github.com/heeler-deer/absorbing/blob/main/png/os-1/1645711286691.pdf">练习题答案</a></p><h1 id="背景知识">背景知识</h1><h2 id="系统概述">系统概述</h2><p>计算机俯视图:</p><p><img src="https://github.com/heeler-deer/absorbing/blob/main/png/os-1/QQ_Image_1645705179108.jpg?raw=true" srcset="/img/loading.gif" lazyload></p><h2 id="指令执行">指令执行</h2><p>本书举了一个例子来描述指令的执行:<img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202202242117220.png" srcset="/img/loading.gif" lazyload></p><p>pc存储指令的地址,存储器相应地址的数值被存放到ir,ir解码把地址940的数据0003放入寄存器ac;之后pc自加1,301的5941被ir解码,使ac的数值与941地址的数值相加;302的2941被ir解码,ac的数被放入地址941中。</p><h2 id="中断">中断</h2><p>在csapp中,一个令人印象深刻的标题叫做“信息就是位+上下文”,os通过执行上下文切换来提供“进程”这一虚拟概念,<img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202202242126552.png" srcset="/img/loading.gif" lazyload></p><p>同时,由于cpu主频远超i/obus的主频,cpu在进行需要大量传输数据的工作时必然会处于空闲状态,因此如何在i/o阻塞时让cpu执行其他工作被叫做“中断”.本书给出了有中断和没有中断的效率对比:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202202242131539.png" srcset="/img/loading.gif" lazyload></p><p>简单的中断通过把必要的上下文压入栈来实现。多个中断通过定义中断优先级来实现。</p><h2 id="存储">存储</h2><p>现代存储器出于cpu对不同区域数据的访问频率不同开发出了不同访问速度的硬件:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202202242138347.png" srcset="/img/loading.gif" lazyload></p><h2 id="io">i/o</h2><p>可编程i/o不具有与处理器的协同工作能力,不具有中断能力,而且处理器只能等待programmedi/o完成;中断驱动i/o显然具有与处理器协同工作的能力,且具有中断能力;DMA直接内存存取则是通过处理器对数据直接读写(通过使用dma模块)来高效完成多字i/o处理。</p><h2 id="结构">结构</h2><p>现代计算机具有:</p><ol type="1"><li>对称多处理器,在进行高并行处理时,这些处理器是等价的</li><li>多核计算机,通过在芯片上直接集成多个处理器、高速缓存来提高计算机的处理能力</li></ol><h2 id="os">os</h2><p>现代操作系统往往提供程序开发、运行,i/o设备访问,文件访问控制,系统访问,错误检测和响应,监控资源等功能。同时,os必须被设计为易于移植的,其结构被描述为:<img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202202261329482.png" srcset="/img/loading.gif" lazyload></p><p>最早的os以<strong>串行方式处理</strong>需求,用户必须手动切换磁盘等来执行程序;在这之后<strong>简单批处理系统</strong>则通过在用户和硬件之间添加一个常驻内核的程序来帮助用户完成对系统的调度,并通过监控程序来实现对处理器的操作。<strong>多道批处理系统</strong>则实现了下图的功能:<img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202202261345590.png" srcset="/img/loading.gif" lazyload></p><p>也即同时处理多个程序(简单来讲)。<strong>分时系统</strong>则是实现了交互模式,即允许多个用户同时访问系统,其原因在于os控制每个用户程序在极短的时间内交替执行用户程序从而令用户感觉像是只有一个人在运行程序。现代操作系统在设计时,往往采用了多种方法,如只给内核最基本的功能(微内核)、分布式设计、采用多线程而不是多进程以及对称多处理的调度方式等.</p><p>一个os的系统可靠性<span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.566ex" xmlns="http://www.w3.org/2000/svg" width="4.294ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 1898 1000"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z"></path></g><g data-mml-node="mo" transform="translate(759,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path></g><g data-mml-node="mi" transform="translate(1148,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mo" transform="translate(1509,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></g></g></g></svg></mjx-container></span>被定义为从t=0到t=t时系统的正确运行概率,其平均失效时间<span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.806ex" xmlns="http://www.w3.org/2000/svg" width="20.236ex" height="2.718ex" role="img" focusable="false" viewBox="0 -845.1 8944.2 1201.5"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D440" d="M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z"></path></g><g data-mml-node="mi" transform="translate(1051,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(1755,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(2459,0)"><path data-c="1D439" d="M48 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H742Q749 676 749 669Q749 664 736 557T722 447Q720 440 702 440H690Q683 445 683 453Q683 454 686 477T689 530Q689 560 682 579T663 610T626 626T575 633T503 634H480Q398 633 393 631Q388 629 386 623Q385 622 352 492L320 363H375Q378 363 398 363T426 364T448 367T472 374T489 386Q502 398 511 419T524 457T529 475Q532 480 548 480H560Q567 475 567 470Q567 467 536 339T502 207Q500 200 482 200H470Q463 206 463 212Q463 215 468 234T473 274Q473 303 453 310T364 317H309L277 190Q245 66 245 60Q245 46 334 46H359Q365 40 365 39T363 19Q359 6 353 0H336Q295 2 185 2Q120 2 86 2T48 1Z"></path></g><g data-mml-node="mo" transform="translate(3485.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path></g><g data-mml-node="msubsup" transform="translate(4541.6,0)"><g data-mml-node="mo" transform="translate(0 0.5)"><path data-c="222B" d="M113 -244Q113 -246 119 -251T139 -263T167 -269Q186 -269 199 -260Q220 -247 232 -218T251 -133T262 -15T276 155T297 367Q300 390 305 438T314 512T325 580T340 647T361 703T390 751T428 784T479 804Q481 804 488 804T501 805Q552 802 581 769T610 695Q610 669 594 657T561 645Q542 645 527 658T512 694Q512 705 516 714T526 729T538 737T548 742L552 743Q552 745 545 751T525 762T498 768Q475 768 460 756T434 716T418 652T407 559T398 444T387 300T369 133Q349 -38 337 -102T303 -207Q256 -306 169 -306Q119 -306 87 -272T55 -196Q55 -170 71 -158T104 -146Q123 -146 138 -159T153 -195Q153 -206 149 -215T139 -230T127 -238T117 -242L113 -244Z"></path></g><g data-mml-node="TeXAtom" transform="translate(699.9,532.6) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="221E" d="M55 217Q55 305 111 373T254 442Q342 442 419 381Q457 350 493 303L507 284L514 294Q618 442 747 442Q833 442 888 374T944 214Q944 128 889 59T743 -11Q657 -11 580 50Q542 81 506 128L492 147L485 137Q381 -11 252 -11Q166 -11 111 57T55 217ZM907 217Q907 285 869 341T761 397Q740 397 720 392T682 378T648 359T619 335T594 310T574 285T559 263T548 246L543 238L574 198Q605 158 622 138T664 94T714 61T765 51Q827 51 867 100T907 217ZM92 214Q92 145 131 89T239 33Q357 33 456 193L425 233Q364 312 334 337Q285 380 233 380Q171 380 132 331T92 214Z"></path></g></g><g data-mml-node="TeXAtom" transform="translate(505,-340.9) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path></g></g></g><g data-mml-node="mi" transform="translate(6165.2,0)"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z"></path></g><g data-mml-node="mo" transform="translate(6924.2,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"></path></g><g data-mml-node="mi" transform="translate(7313.2,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g><g data-mml-node="mo" transform="translate(7674.2,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"></path></g><g data-mml-node="mi" transform="translate(8063.2,0)"><path data-c="1D451" d="M366 683Q367 683 438 688T511 694Q523 694 523 686Q523 679 450 384T375 83T374 68Q374 26 402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487H491Q506 153 506 145Q506 140 503 129Q490 79 473 48T445 8T417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157Q33 205 53 255T101 341Q148 398 195 420T280 442Q336 442 364 400Q369 394 369 396Q370 400 396 505T424 616Q424 629 417 632T378 637H357Q351 643 351 645T353 664Q358 683 366 683ZM352 326Q329 405 277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q233 26 290 98L298 109L352 326Z"></path></g><g data-mml-node="mi" transform="translate(8583.2,0)"><path data-c="1D461" d="M26 385Q19 392 19 395Q19 399 22 411T27 425Q29 430 36 430T87 431H140L159 511Q162 522 166 540T173 566T179 586T187 603T197 615T211 624T229 626Q247 625 254 615T261 596Q261 589 252 549T232 470L222 433Q222 431 272 431H323Q330 424 330 420Q330 398 317 385H210L174 240Q135 80 135 68Q135 26 162 26Q197 26 230 60T283 144Q285 150 288 151T303 153H307Q322 153 322 145Q322 142 319 133Q314 117 301 95T267 48T216 6T155 -11Q125 -11 98 4T59 56Q57 64 57 83V101L92 241Q127 382 128 383Q128 385 77 385H26Z"></path></g></g></g></svg></mjx-container></span>,平均修复时间MTTR则指修复或替换错误所花费的平均时间,因此一个系统的可用性<span class="math inline"><mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.912ex" xmlns="http://www.w3.org/2000/svg" width="17.234ex" height="2.896ex" role="img" focusable="false" viewBox="0 -877 7617.6 1279.9"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D434" d="M208 74Q208 50 254 46Q272 46 272 35Q272 34 270 22Q267 8 264 4T251 0Q249 0 239 0T205 1T141 2Q70 2 50 0H42Q35 7 35 11Q37 38 48 46H62Q132 49 164 96Q170 102 345 401T523 704Q530 716 547 716H555H572Q578 707 578 706L606 383Q634 60 636 57Q641 46 701 46Q726 46 726 36Q726 34 723 22Q720 7 718 4T704 0Q701 0 690 0T651 1T578 2Q484 2 455 0H443Q437 6 437 9T439 27Q443 40 445 43L449 46H469Q523 49 533 63L521 213H283L249 155Q208 86 208 74ZM516 260Q516 271 504 416T490 562L463 519Q447 492 400 412L310 260L413 259Q516 259 516 260Z"></path></g><g data-mml-node="mo" transform="translate(1027.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path></g><g data-mml-node="mfrac" transform="translate(2083.6,0)"><g data-mml-node="mrow" transform="translate(1632.8,394) scale(0.707)"><g data-mml-node="mi"><path data-c="1D440" d="M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z"></path></g><g data-mml-node="mi" transform="translate(1051,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(1755,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(2459,0)"><path data-c="1D439" d="M48 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H742Q749 676 749 669Q749 664 736 557T722 447Q720 440 702 440H690Q683 445 683 453Q683 454 686 477T689 530Q689 560 682 579T663 610T626 626T575 633T503 634H480Q398 633 393 631Q388 629 386 623Q385 622 352 492L320 363H375Q378 363 398 363T426 364T448 367T472 374T489 386Q502 398 511 419T524 457T529 475Q532 480 548 480H560Q567 475 567 470Q567 467 536 339T502 207Q500 200 482 200H470Q463 206 463 212Q463 215 468 234T473 274Q473 303 453 310T364 317H309L277 190Q245 66 245 60Q245 46 334 46H359Q365 40 365 39T363 19Q359 6 353 0H336Q295 2 185 2Q120 2 86 2T48 1Z"></path></g></g><g data-mml-node="mrow" transform="translate(220,-345) scale(0.707)"><g data-mml-node="mi"><path data-c="1D440" d="M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z"></path></g><g data-mml-node="mi" transform="translate(1051,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(1755,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(2459,0)"><path data-c="1D439" d="M48 1Q31 1 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H742Q749 676 749 669Q749 664 736 557T722 447Q720 440 702 440H690Q683 445 683 453Q683 454 686 477T689 530Q689 560 682 579T663 610T626 626T575 633T503 634H480Q398 633 393 631Q388 629 386 623Q385 622 352 492L320 363H375Q378 363 398 363T426 364T448 367T472 374T489 386Q502 398 511 419T524 457T529 475Q532 480 548 480H560Q567 475 567 470Q567 467 536 339T502 207Q500 200 482 200H470Q463 206 463 212Q463 215 468 234T473 274Q473 303 453 310T364 317H309L277 190Q245 66 245 60Q245 46 334 46H359Q365 40 365 39T363 19Q359 6 353 0H336Q295 2 185 2Q120 2 86 2T48 1Z"></path></g><g data-mml-node="mo" transform="translate(3208,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z"></path></g><g data-mml-node="mi" transform="translate(3986,0)"><path data-c="1D440" d="M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z"></path></g><g data-mml-node="mi" transform="translate(5037,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(5741,0)"><path data-c="1D447" d="M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z"></path></g><g data-mml-node="mi" transform="translate(6445,0)"><path data-c="1D445" d="M230 637Q203 637 198 638T193 649Q193 676 204 682Q206 683 378 683Q550 682 564 680Q620 672 658 652T712 606T733 563T739 529Q739 484 710 445T643 385T576 351T538 338L545 333Q612 295 612 223Q612 212 607 162T602 80V71Q602 53 603 43T614 25T640 16Q668 16 686 38T712 85Q717 99 720 102T735 105Q755 105 755 93Q755 75 731 36Q693 -21 641 -21H632Q571 -21 531 4T487 82Q487 109 502 166T517 239Q517 290 474 313Q459 320 449 321T378 323H309L277 193Q244 61 244 59Q244 55 245 54T252 50T269 48T302 46H333Q339 38 339 37T336 19Q332 6 326 0H311Q275 2 180 2Q146 2 117 2T71 2T50 1Q33 1 33 10Q33 12 36 24Q41 43 46 45Q50 46 61 46H67Q94 46 127 49Q141 52 146 61Q149 65 218 339T287 628Q287 635 230 637ZM630 554Q630 586 609 608T523 636Q521 636 500 636T462 637H440Q393 637 386 627Q385 624 352 494T319 361Q319 360 388 360Q466 361 492 367Q556 377 592 426Q608 449 619 486T630 554Z"></path></g></g><rect width="5294" height="60" x="120" y="220"></rect></g></g></g></svg></mjx-container></span></p><p>现在操作系统主要分为windows,bsd,linux,mac这四类。其中linux是由很多模块组成的,这些<code>可加载模块</code>的两个重要特征是<strong>动态连接和可堆叠模块</strong>.动态连接指内核模块可被随时加载连接到内核,或者随时被断开连接移除内存。可堆叠模块指模块按照层次结构排列,多个类似模块可移到单个模块中,便于模块加载。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202203062005301.png" srcset="/img/loading.gif" lazyload></p><h1 id="进程">进程</h1><h2 id="进程描述和控制">进程描述和控制</h2><p>os要确保资源对所有程序可用,并且要在多个程序之间切换,保证资源能够得到充分利用,<strong>进程</strong>就是os为了方便管理而提出的概念。进程的基本元素是<strong>程序代码</strong>和相关<strong>数据集</strong>,在进程执行的任意时刻,可以由如下元素表示:</p><ul><li>标识符:唯一的标识符号</li><li>状态:如运行,阻塞,就绪</li><li>优先级:进程之间的优先顺序</li><li>程序计数器:pc</li><li>内存指针:程序代码和进程相关数据的指针,以及与其他进程共享内存块的指针</li><li>上下文数据: 执行进程时处理器的寄存器中的数据</li><li>I/O状态信息:显式i/o请求,分配的i/o设备和被进程使用的文件列表等</li><li>记账信息:包括处理器时间总和、使用的时钟数总和、时间限制、记账号等</li></ul><p>这些信息被存储在进程控制块中:<img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202203062039366.png" srcset="/img/loading.gif" lazyload></p><h3 id="五状态模型">五状态模型</h3><p>os要对进程进行处理,考虑这样的情况:假设处理器以轮转方式操作进程,即以一种单个队列里先进先出的方式处理进程,那会怎样?显然,会存在一些处于非运行态但已经就绪的进程,不能只考虑”最老“的进程.作者提出了这样一个五状态模型:</p><ol type="1"><li>运行态:进程执行</li><li>就绪态:进程做好准备,有机会就执行</li><li>阻塞态:进程在某些事件发生前不能执行</li><li>新建态:os尚未把他加入可执行进程组</li><li>退出态:os从可执行进程组中释放出的进程</li></ol><h3 id="挂起">挂起</h3><p>对于五状态模型,我们可以按照多级队列、设置进程优先级等方式提高cpu的利用率。</p><p>但是还存在这样一种情况:内存中的所有进程都在等待i/o,此时cpu未进行对进程的任何处理,直至i/o完成才能继续。</p><p>为了更高效率的使用cpu,我们需要把等待i/o的一些进程<strong>挂起</strong>到内存之外,使cpu此时可以处理其他不需要i/o的进程。</p><p>这种 <code>交换技术</code>是把内存中某个进程的一部分转移到磁盘中。</p><p>我们加入挂起状态后的模型如下:</p><ul><li>就绪态</li><li>阻塞态</li><li>阻塞/挂起态</li><li>就绪/挂起态</li><li>新建态</li><li>运行态</li><li>退出态</li></ul><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204151018890.png" srcset="/img/loading.gif" lazyload></p><p><strong>操作系统控制表的通用结构:</strong></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204151020881.png" srcset="/img/loading.gif" lazyload></p><p><strong>进程控制块的元素:</strong></p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204151030840.png" srcset="/img/loading.gif" lazyload></p><p>上图从上到下分别是进程标识信息,进程状态信息,进程控制信息</p><h3 id="进程控制">进程控制</h3><p>进程分为用户模式和内核模式。</p><p>在64位IA-64结构的intel itanium处理器中,就包含了一个current privilegelevel的2位字段去指示当前进程的特权级别。</p><p>在进程创建的时候,每一个进程都会有一个唯一的标识符,一些空间,os会初始化进程控制块,并做一些其他的操作。</p><p>那么进程之间如何切换呢?</p><p>进程切换即把控制权交给os,在由os进行处理,可以是中断(来自当前执行进程的外部)、陷阱(当前进程相关)以及系统的显式调用。对于普通中断,控制权会先被移交给中断处理器,中断处理器进行一些工作后在将控制权移交给相关的os例程。对于陷阱,os会先判断是否致命。系统调用则发生在如进程i/o时对用户态的处理。</p><p>由此分为模式切换以及进程切换两种切换模式。对于 <code>模式切换</code>,在发生中断时,pc被置为中欧你那个段处理程序的开始地址,从用户模式切换到内核模式,之后的做法取决于之后的信息。模式切换可以不改变进程的状态。对于进程切换,往往需要比模式切换更多的开销,os必须使进程的环境发生实质性变换。</p><h2 id="线程">线程</h2><p>在之前的讨论中,进程的两个特点是资源所有权以及调度/执行权利,但在实际上,这两个特点是独立的,操作系统为了区分他们,通常将调度/执行权称为线程/轻量级进程,将资源所有权称为进程。所谓多线程,指的是os在<code>单个进程</code>内支持多个并发执行路径的能力。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204172131830.png" srcset="/img/loading.gif" lazyload></p><p>在多线程环境中,进程被定义为一个资源分配单位以及一个保护单位,进程中的所有线程共享该进程的状态和资源。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204172133561.png" srcset="/img/loading.gif" lazyload></p><p>书中举了这样一个例子,文件服务器对每一个新的文件请求都会创建一个新线程,实质上加快了系统处理的能力。</p><p>改变线程状态的四种基本操作是:</p><ul><li>派生,新建进程时会为该进程派生一个线程,线程可以派生另一个线程,并提供相关指针,新线程存放在就绪队列中。实质上我觉得是一种虚拟化技术,通过派生把进程线程统一起来。</li><li>阻塞,和进程类似</li><li>解除阻塞</li><li>结束,线程结束时释放寄存器上下文以及栈</li></ul><p>有一个叫RPC的以前没听过:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204172141437.png" srcset="/img/loading.gif" lazyload></p><p>用户级线程以及内核级线程的直观表示:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204260835893.png" srcset="/img/loading.gif" lazyload></p><p>user-levelthread的优点在于对每一个应用程序都可以定制,可以对任何os制定不同的算法,但不可以利用多处理技术,相当于运行多个程序执行同一件事,无法利用多处理器的效率。书中列举了不同os的线程和进程之间的比例关系,</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204260838199.png" srcset="/img/loading.gif" lazyload></p><p>我比较好奇的是trix的M:N以及适用于分布式操作系统的1:M的ra操作系统。</p><p>现在讨论一下linux中的进程和线程管理。</p><p>linux的进程由一个task_struct数据结构表示,这个数据结构包含该进程的状态,调度信息,标识符,进程间通信,以及进程到其父进程、兄弟进程的链接,除此之外还包含时间信息、文件系统等。</p><p>linux实际上并不区分进程和线程,若两个进程共享相同的虚存,则可以把他们视为一个进程中的线程。其中线程并没有数据结构的定义。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204260919835.png" srcset="/img/loading.gif" lazyload></p><p>linux中和每一个进程相关联的是一组命名空间,命名空间使得进程看起来像是系统上唯一的进程。当前linux有6中命名空间,</p><ul><li>mnt,为进程提供文件系统层次结构的视图</li><li>uts,即unix timesharing,</li><li>ipc,隔离某些进程间通信资源,通过ipc可以控制进程间的通信</li><li>pid,隔离进程id空间,可以使不同pid命名空间的进程有相同的pid,如criu项目,就可以冻结一个正在运行的程序,把他放到硬盘中作为一个文件集。criu冻结的程序可以被恢复。</li><li>网络命名空间,用于隔离与网络相关的系统资源,包括网络设备,ip地址,ip路由表,端口号等。</li><li>用户命名空间,当一个进程克隆一个新进程的时候,可以为新进程一个新的用户命名空间,新的pid命名空间和其他所有命名空间。</li></ul><h2 id="并发性互斥和同步">并发性:互斥和同步</h2><p>并发是解决多道程序设计技术、多处理器技术、分布式处理器技术的基础,相关术语:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204260939225.png" srcset="/img/loading.gif" lazyload></p><h3 id="并发的原理">并发的原理</h3><p>考虑代码:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">echo</span><span class="hljs-params">()</span></span>{<br> chin=getchar();<br> chout=chin;<br> <span class="hljs-built_in">putchar</span>(chout);<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>假如两个进程都用到该代码,os把该代码放到共享空间,那么假设在进程1调用echo时,putchar没有来得及执行,此时进程2调用echo,那么就会出现进程1的chin丢失的情况。</p><p>这意味着只有控制访问该变量的代码才能保护共享的全局变量。这意味着操作系统必须能够跟踪不同的进程,为进程分配释放并保护资源,同时必须保证一个进程的功能和输出结果必须与执行速度无关(硬件上实现类似功能的叫DR,生活上实现类似功能的叫菜鸟驿站)</p><p>进程交互:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202204262024379.png" srcset="/img/loading.gif" lazyload></p><p>进程竞争面临三个控制问题。</p><ul><li>互斥,假设多个进程访问不可共享的资源如打印机,这时我们把打印机这种资源称为临界资源,使用临界资源的程序称为临界区,一次只允许一个程序在临界区中。由此产生另外两个控制问题,死锁以及饥饿。</li><li>死锁,即进程1和进程2分别占据资源r1,r2时,进程1需要再加上资源r2才能释放r1,进程2需要资源r1才能释放r2的情况。此时进程12都不会释放自己的资源。</li><li>饥饿指新加的进程3始终无法使用上述资源r1/r2的情况,也可以是os在分配资源时始终不分配给进程3的情况。</li></ul><h3 id="互斥硬件">互斥——硬件</h3><p>在早期的单处理器机器中,只需要保证临界区资源不被中断即可,通过在临界区之后启用中断来实现即可。代价是处理器只能交替执行程序,且只适合单处理器使用。</p><p>后来人们开始使用专用机器指令,这些指令保证了两个动作的原子性。常见的指令有compare&swap以及,这些指令不接受中断</p><p>compare&swap</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">compare_and_swap</span><span class="hljs-params">(<span class="hljs-keyword">int</span> *word,<span class="hljs-keyword">int</span> testval,<span class="hljs-keyword">int</span> newval)</span></span>{<br> <span class="hljs-keyword">int</span> oldval;<br> oldval=*word;<br> <span class="hljs-keyword">if</span>(oldval==testval)*word=newval;<br> <span class="hljs-keyword">return</span> oldval;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>基于这个指令的互斥规程是这样的:共享变量被初始化为0,唯一可以进入临界区的进程是发现共享变量为0的进程,其他进程则处于spinwaiting的状态。</p><p>exchange:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">exhange</span><span class="hljs-params">(<span class="hljs-keyword">int</span> *reg,<span class="hljs-keyword">int</span> *memory)</span></span>{<br> <span class="hljs-keyword">int</span> temp;<br> temp=*memory;<br> *memory=*reg;<br> *reg=temp;<br>}<br></code></pre></div></td></tr></tbody></table></figure><p>该指令的互斥规程类似于compare_and_swap</p><p>上述机器指令实现了对多个处理器以及多个临界区的处理,但仍然没有解决饥饿、死锁等问题。</p><h3 id="常用的并发机制">常用的并发机制</h3><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205032017071.png" srcset="/img/loading.gif" lazyload></p><h4 id="信号量">信号量</h4><p>基本思路是进程间通过信号量进行合作,首先把信号量初始化为非负数,semWait使操作数减一,semSignal使操作数加一,信号量为负数时执行semWait的进程被阻塞,而在信号量为负数的情况下每一个semSignal操作都会使等待进程中的一个进程解除阻塞。需要注意的是,每一个进程都可以执行smeWait以及semSignal,共享一个信号量;而为互斥量加锁的进程和为互斥量解锁的进程必须是同一个。</p><h4 id="管程">管程</h4><p>信号量的缺点在于semWait以及semSignal可能分布在整个程序中,很难看出信号量的操作所产生的整体效果。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205041751170.png" srcset="/img/loading.gif" lazyload></p><p>管程则更易于控制。它是由多个过程、一个初始化序列和局部数据块组成。管程中只能有一个进程在执行,进程通过调用管程来进入管程。那么管程如何实现类似于并发管理的功能?一个方法是采用类似于信号量的条件变量,缺点是仍然具有信号量所具有的问题。另一个方法是采用类似网络中的通知和广播结构,这样的方法错误较少。</p><h4 id="消息传递">消息传递</h4><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205041757824.png" srcset="/img/loading.gif" lazyload></p><p>进程的交互需要同步和通信这两个基本需求;通信以一对原语实现:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">send(destination,message);<br>receive(source,message);<br></code></pre></div></td></tr></tbody></table></figure><p>通常来讲,发送者和接收者都可以阻塞或者不阻塞。其中无阻塞send、阻塞receive是最自然的。send以及receive通过直接寻址和间接寻址确定目标或者源进程。间接寻址时,消息存储到一个叫做<strong>信箱</strong>的数据结构中,以更灵活的传递消息。</p><p>消息格式一般以定长短消息来减小额外开销,以生成文件并传递文件信息来传递大量数据,或者通过变长消息传递。</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205041811471.png" srcset="/img/loading.gif" lazyload></p><h4 id="读者写者问题">读者/写者问题</h4><p>该问题定义如下:</p><p>存在一个多个进程共享的数据区域,有些进程只读数据,有些进程只写数据,且</p><ol type="1"><li>任意数量的进程可以同时读这个文件</li><li>一次只有一个进程可以写文件</li><li>若一个进程在写文件,则禁止任何进程读文件</li></ol><p>书中给出了读者优先以及写者优先两中解决</p><h3 id="死锁和饥饿">死锁和饥饿</h3><p>死锁实例:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205100808130.png" srcset="/img/loading.gif" lazyload></p><p>从图上我们可以认知到,死锁的发生与系统的资源调度有关,他取决于动态执行方式以及应用程序。可重用资源以及可消耗资源(中断,信号量等)都可能造成死锁,资源分配图:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205100847200.png" srcset="/img/loading.gif" lazyload></p><p>书中总结了死锁的可能性/存在性所需的条件:</p><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205100849076.png" srcset="/img/loading.gif" lazyload></p><p><strong>死锁避免</strong>主要通过不启动导致死锁的进程+不允许导致死锁的资源分配实现。</p><ul><li>不启动导致死锁的进程,考虑一个n个进程以及m种不同类型资源的系统,</li></ul><p><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202205112122338.png" srcset="/img/loading.gif" lazyload></p><p>显然,合理的想法是仅当 $R_{j} C_{(n+1)j} + <em>{n}^{i=1}C</em>{ij} $时才可以启动一个新的进程n+1</p><ul><li>资源分配拒绝策略,又叫银行家算法,他定义了安全状态以及不安全状态,所谓的<strong>安全状态</strong>即至少有一个资源分配序列不会导致死锁。</li></ul><p>资源分配避免实质上就是通过预测分配资源后系统是否是安全状态来决定是否分配资源,他看到了当前的一步,确保不会出现死锁。</p><h1 id="内存">内存</h1><h1 id="调度">调度</h1><h1 id="io-1">I/O</h1><h1 id="嵌入式">嵌入式</h1><h1 id="online">online</h1>]]></content>
<summary type="html"><h1 id="知识补全计划">知识补全计划</h1>
<p>目前打算按以下顺序补完: <a href="https://zh.u1lib.org/book/16404075/f41379">操作系统:精髓与设计原理</a></p>
<p><a href="https://zh.</summary>
<category term="读书" scheme="https://heeler-deer.top/categories/%E8%AF%BB%E4%B9%A6/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="os" scheme="https://heeler-deer.top/tags/os/"/>
</entry>
<entry>
<title>vps</title>
<link href="https://heeler-deer.top/posts/490e9480/"/>
<id>https://heeler-deer.top/posts/490e9480/</id>
<published>2021-11-13T15:32:44.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="起因">起因</h1><p> 一直以来,我奉行的都是<strong>白嫖</strong>政策:编辑器白嫖,github白嫖,微信读书白嫖,当别人买域名时我却一直在用github提供的服务,从未在网络上付过费,毕竟网络水太深,我把握不住<span class="github-emoji"><span>💔</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f494.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span> 但当我的lantern(懂得都懂)不小心被我删了后(listary的启动和卸载两个选项离得太近!),我开始琢磨怎么自己实现科学上网。于是我开始用bing搜索起教程,最终找到了前人铺好的路,并实现了我的目标<span class="github-emoji"><span>💥</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f4a5.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><h1 id="过程">过程</h1><p> 接下来,我将复盘我科学上网、ipv6免流、搭建ftp的过程。</p><h2 id="参考连接">参考连接</h2><p><a href="https://github.com/alvin9999/new-pac/wiki/%E8%87%AA%E5%BB%BAss%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%95%99%E7%A8%8B">自建ssr服务+校园网免流</a><a href="https://www.cnblogs.com/sopcce/p/10743241.html">ftp搭建</a></p><h2 id="过程-1">过程</h2><p> 既然要科学上网,就必须选择国内外都没有被墙的ip,我选择的是vultr,5$的centos7x(withoutselinux),这个配置内核版本比较低,不会有奇奇怪怪的防火墙导致的错误。 因为网上一直有亚洲的vultr节点被墙的说法,我选择了newyork的服务,虽然确实慢了点,但风险较小。如果你想实现校园网免流,记得勾选enableipv6 <img src="https://github.com/heeler-deer/absorbing/blob/main/png/Camera%20Roll/fir.png?raw=true" srcset="/img/loading.gif" lazyload> 这是某次我创建是的截图,现在该云主机已销毁: <img src="https://github.com/heeler-deer/absorbing/blob/main/png/Camera%20Roll/de.png?raw=true" srcset="/img/loading.gif" lazyload> 在云主机配置好后,我们需要一个办法远程连接这台主机,当然你直接在vultr的控制台连接也行。 远程连接使用xshell,可以用学校邮箱白嫖免费的版本----我第一次注册湖大的邮箱就白嫖<span class="github-emoji"><span>😰</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f630.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span> 如果你和我一样,想要让多个人使用你的ssr,那么使用第一个参考连接的脚本,使用下面的配置:</p><figure class="highlight c"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs c">wget -N --no-check-certificate https:<span class="hljs-comment">//raw.githubusercontent.com/ToyoDAdoubiBackup/doubi/master/ssrmu.sh && chmod +x ssrmu.sh && bash ssrmu.sh</span><br></code></pre></div></td></tr></tbody></table></figure><p> 最终按照提示,可以一步步完成ssr的配置,需要注意的是,我刚开始并没有搭建好ssr服务,在用邮箱问过第一个参考连接的作者后,采用了如下的配置,这些都可以在你启动ssr前选择好:</p><figure class="highlight maxima"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs maxima"><br>加密<br>chacha20<br><br><br>协议<br><span class="hljs-built_in">origin</span><br><br><br>混淆<br>tls1.2_ticket_auth<br></code></pre></div></td></tr></tbody></table></figure><p> <strong>注意:</strong>如果你是采用我博客中的wget连接安装脚本,启动脚本的方式就是最后的<code>bash ssrmu.sh</code>,而当你开启脚本并选择的上面的加密、协议、混淆方式后,需要选择4来安装那个libsodium,这样才能启动脚本。 启动脚本后,采用第一个参考连接,服务端启动ssr的加速。之后在你的电脑或移动设备上下载shadowsockr或者v2ray就可以科学上网,这些第一个参考链接里都有下载方式。</p><hr><p> 之后,在你的电脑端填入你的vps的ipv6地址就可以实现校园网ipv6免流了。</p><figure class="highlight smali"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs smali">原理简介:通过使用代理,在本地请求后以ipv6的方式发送给代理,在由代理获得数据后以ipv6的方式返回给本地。<br></code></pre></div></td></tr></tbody></table></figure><p> 也就是说,必须要校园网支持ipv6免流才可行。对于手机,由于其不能被HNU的校园网识别为电脑,因此在配置ssr时不能填入服务器的ipv6地址,也就无法实现免流,</p><hr><p> 接下来我搭建了一个简易的ftp服务器,参考第二个连接。 此处不再赘述。需要注意的是,/etc/vsftpd/vsftpd.conf中,要满足:</p><figure class="highlight ini"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ini"><span class="hljs-attr">userlist_deny</span>=<span class="hljs-literal">YES</span><br></code></pre></div></td></tr></tbody></table></figure><p> 这样设置好的ftp就可以正常使用了。虽然使用filezilla比较慢,简易的服务也无法和各大云盘比较,但一个月5$总要多用用<span class="github-emoji"><span>😏</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f60f.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span> 如果你在尝试的时候不小心把sopftpuser的一些文件删了,可以像我一样采用重新创建同名文件并赋予777权限的方法挽救损失<span class="github-emoji"><span>🙌</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f64c.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><h1 id="总结">总结</h1><p> ( •̀ ω •́)y我会了linux的基本操作了,尤其是vim这些对文件的基本操作。虽然自己有一个物理机ubuntu,但一直都是图形化操作,这次算是熟练使用了vim的命令行操作。了解了firewall-cmd以及selinux的ufw这些防火墙的操作,之前一直因为icmp开放而tcp不开放纠结<span class="github-emoji"><span>🙉</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f649.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span> 此处感谢<a href="https://kiprey.github.io/">Kipery</a>以及众多愿意在网上分享技术的网友们<span class="github-emoji"><span>❤</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/2764.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span><strong>附连接</strong>: <a href="https://www.toolsdaquan.com/ipcheck/">ip可用性检测国内外icmp+tcp</a><a href="http://test-ipv6.com/index.html.zh_CN">ipv6检测</a></p>]]></content>
<summary type="html"><h1 id="起因">起因</h1>
<p> 一直以来,我奉行的都是<strong>白嫖</strong>政策:编辑器白嫖,github白嫖,微信读书白嫖,当别人买域名时我却一直在用github提供的服务,从未在网络上付过费,毕竟网络水太深,我把握不住<span class=</summary>
<category term="瞎搞" scheme="https://heeler-deer.top/categories/%E7%9E%8E%E6%90%9E/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
<category term="花里胡哨" scheme="https://heeler-deer.top/tags/%E8%8A%B1%E9%87%8C%E8%83%A1%E5%93%A8/"/>
</entry>
<entry>
<title>makefile</title>
<link href="https://heeler-deer.top/posts/9d37c3fa/"/>
<id>https://heeler-deer.top/posts/9d37c3fa/</id>
<published>2021-10-20T01:50:24.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="前言">前言</h1><p>这几天的实验让我觉得有必要学习一下makefile 参考博客:<a href="https://seisman.github.io/how-to-write-makefile/overview.html">博客</a></p><blockquote><p>会不会写makefile,从一个侧面说明了一个人是否具有完成大型工程的能力</p></blockquote><p>makefile带来的好处是自动化编译</p><h1 id="规则">规则</h1><figure class="highlight jboss-cli"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs jboss-cli">target.<span class="hljs-string">..</span><span class="hljs-function">:prerequisites...</span><br> <span class="hljs-keyword">command</span><br> <span class="hljs-string">...</span><br> <span class="hljs-string">...</span><br></code></pre></div></td></tr></tbody></table></figure><p>target是一个objectfile,可以是一个执行文件,也可以是一个标签preerquisites是依赖的文件command是shell命令</p><blockquote><p>prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。</p></blockquote><p>看看例子:</p><figure class="highlight vim"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vim"><span class="hljs-keyword">edit</span> : main.<span class="hljs-keyword">o</span> kbd.<span class="hljs-keyword">o</span> <span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> \<br> <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> <span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> utils.<span class="hljs-keyword">o</span><br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">o</span> <span class="hljs-keyword">edit</span> main.<span class="hljs-keyword">o</span> kbd.<span class="hljs-keyword">o</span> <span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> \<br> <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> <span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> utils.<span class="hljs-keyword">o</span><br><br>main.<span class="hljs-keyword">o</span> : main.<span class="hljs-keyword">c</span> defs.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> main.<span class="hljs-keyword">c</span><br>kbd.<span class="hljs-keyword">o</span> : kbd.<span class="hljs-keyword">c</span> defs.h <span class="hljs-keyword">command</span>.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> kbd.<span class="hljs-keyword">c</span><br><span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> : <span class="hljs-keyword">command</span>.<span class="hljs-keyword">c</span> defs.h <span class="hljs-keyword">command</span>.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> <span class="hljs-keyword">command</span>.<span class="hljs-keyword">c</span><br><span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> : <span class="hljs-keyword">display</span>.<span class="hljs-keyword">c</span> defs.h <span class="hljs-keyword">buffer</span>.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> <span class="hljs-keyword">display</span>.<span class="hljs-keyword">c</span><br><span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> : <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">c</span> defs.h <span class="hljs-keyword">buffer</span>.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">c</span><br><span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> : <span class="hljs-built_in">search</span>.<span class="hljs-keyword">c</span> defs.h <span class="hljs-keyword">buffer</span>.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> <span class="hljs-built_in">search</span>.<span class="hljs-keyword">c</span><br><span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> : <span class="hljs-keyword">files</span>.<span class="hljs-keyword">c</span> defs.h <span class="hljs-keyword">buffer</span>.h <span class="hljs-keyword">command</span>.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> <span class="hljs-keyword">files</span>.<span class="hljs-keyword">c</span><br>utils.<span class="hljs-keyword">o</span> : utils.<span class="hljs-keyword">c</span> defs.h<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">c</span> utils.<span class="hljs-keyword">c</span><br>clean :<br> rm <span class="hljs-keyword">edit</span> main.<span class="hljs-keyword">o</span> kbd.<span class="hljs-keyword">o</span> <span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> \<br> <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> <span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> utils.<span class="hljs-keyword">o</span><br></code></pre></div></td></tr></tbody></table></figure><p>其中,,便于make阅读,最后的clean只是一个<code>动作名字</code>,清除生成的中间文件。在编写command时,此行一定要以<strong>tab</strong>开头,空格也不行。</p><h2 id="上述make的工作方式">上述make的工作方式</h2><ol type="1"><li>make寻找名为<code>makefile</code>或者<code>Makefile</code>的文件</li><li>寻找第一个目标文件,上述例子edit为最终的目标文件</li><li>如果edit文件不存在,那么make会寻找edit后的.o文件,如果edit依赖的.o文件仍然不存在,那make就寻找目标文件是.o文件的文件。一直套娃下去</li><li>最终生成可执行文件</li></ol><blockquote><p>在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。<strong>make只管文件的依赖性</strong>,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦</p></blockquote><p>上述例子中的clean没有被edit直接/间接关联,则make不会自动执行。输入</p><figure class="highlight ebnf"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ebnf"><span class="hljs-attribute">make clean</span><br></code></pre></div></td></tr></tbody></table></figure><p>才可以执行</p><h2 id="变量">变量</h2><p>出于对makefile的易维护性的考虑,引入了变量的概念:</p><figure class="highlight vim"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vim">objects=main.<span class="hljs-keyword">o</span> kbd.<span class="hljs-keyword">o</span> <span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> \<br> <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> <span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> utils.<span class="hljs-keyword">o</span><br><span class="hljs-keyword">edit</span> : $(objects)<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">o</span> <span class="hljs-keyword">edit</span> $(objects)<br></code></pre></div></td></tr></tbody></table></figure><p>末尾的clean变为:</p><figure class="highlight makefile"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs makefile"><span class="hljs-section">clean:</span><br> rm edit <span class="hljs-variable">$(objects)</span><br></code></pre></div></td></tr></tbody></table></figure><h2 id="自动推导">自动推导</h2><p>GNU的make可以自动推导文件的依赖关系以及命令,于是上述例子可以变为:</p><figure class="highlight vim"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vim">objects = main.<span class="hljs-keyword">o</span> kbd.<span class="hljs-keyword">o</span> <span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> \<br> <span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> <span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> <span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> utils.<span class="hljs-keyword">o</span><br><br><span class="hljs-keyword">edit</span> : $(objects)<br> <span class="hljs-keyword">cc</span> -<span class="hljs-keyword">o</span> <span class="hljs-keyword">edit</span> $(objects)<br><br>main.<span class="hljs-keyword">o</span> : defs.h<br>kbd.<span class="hljs-keyword">o</span> : defs.h <span class="hljs-keyword">command</span>.h<br><span class="hljs-keyword">command</span>.<span class="hljs-keyword">o</span> : defs.h <span class="hljs-keyword">command</span>.h<br><span class="hljs-keyword">display</span>.<span class="hljs-keyword">o</span> : defs.h <span class="hljs-keyword">buffer</span>.h<br><span class="hljs-keyword">insert</span>.<span class="hljs-keyword">o</span> : defs.h <span class="hljs-keyword">buffer</span>.h<br><span class="hljs-built_in">search</span>.<span class="hljs-keyword">o</span> : defs.h <span class="hljs-keyword">buffer</span>.h<br><span class="hljs-keyword">files</span>.<span class="hljs-keyword">o</span> : defs.h <span class="hljs-keyword">buffer</span>.h <span class="hljs-keyword">command</span>.h<br>utils.<span class="hljs-keyword">o</span> : defs.h<br><br>.PHONY : clean<br>clean :<br> rm <span class="hljs-keyword">edit</span> $(objects)<br></code></pre></div></td></tr></tbody></table></figure><p>极大减少了代码量</p><h2 id="清空clean">清空clean</h2><figure class="highlight makefile"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs makefile"><span class="hljs-meta"><span class="hljs-meta-keyword">.PHONY</span>: clean</span><br><span class="hljs-section">clean:</span><br> -rm edit <span class="hljs-variable">$(objects)</span><br></code></pre></div></td></tr></tbody></table></figure><p>.PHONY是一个伪目标,rm前的<code>-</code>告诉make也许某些文件会出现问题,但不要管,继续clean</p><h2 id="makefile的文件系统">makefile的文件系统</h2><p>如果你不想使用<code>makefile</code>或者<code>Makefile</code>的文件名,可以用<code>make -f file</code>,file是你的文件名。makefile中包含其他makefile的指令如同c++ 一样:</p><figure class="highlight stylus"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus">-include foo<span class="hljs-selector-class">.make</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.mk</span> <span class="hljs-selector-tag">b</span><span class="hljs-selector-class">.mk</span> c<span class="hljs-selector-class">.mk</span> e<span class="hljs-selector-class">.mk</span> f.mk<br></code></pre></div></td></tr></tbody></table></figure><p>减号仍然表示不管怎样报错都继续执行下去,上面的命令可以采用部分正则规则简化:</p><figure class="highlight haml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs haml">-<span class="ruby"><span class="hljs-keyword">include</span> foo,make *,mk <span class="hljs-variable">$(</span>bar)</span><br></code></pre></div></td></tr></tbody></table></figure><h2 id="工作方式">工作方式</h2><ol type="1"><li>读入所有的Makefile。</li><li>读入被include的其它Makefile。</li><li>初始化文件中的变量。</li><li>推导隐晦规则,并分析所有规则。</li><li>为所有的目标文件创建依赖关系链。</li><li>根据依赖关系,决定哪些目标要重新生成。</li><li>执行生成命令。</li></ol><h1 id="书写规则">书写规则</h1><p>make支持三个通配符:</p><figure class="highlight ruby"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ruby">*,<span class="hljs-string">?,</span>~<br></code></pre></div></td></tr></tbody></table></figure><p>make可以在别的文件夹下寻找文件:</p><figure class="highlight ini"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ini"><span class="hljs-attr">VPATH</span>=src:../headers<br></code></pre></div></td></tr></tbody></table></figure><p>如果make没有在当前文件夹下找到文件,就回去VPATH的路径下寻找文件,另一种方法是使用更为灵活的vpath:</p><figure class="highlight dts"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs dts">vpath <span class="hljs-params"><pattern></span> <span class="hljs-params"><directories></span><br><span class="hljs-meta"># 为符合模式的文件指定搜索目录</span><br>vpath <span class="hljs-params"><pattern></span><br><span class="hljs-meta"># 清除符合模式的文件的搜索目录</span><br>vpath<br><span class="hljs-meta"># 清除所有已被设置好的文件搜索目录</span><br></code></pre></div></td></tr></tbody></table></figure><p>pattern需要包含%,表示匹配0/若干字符,例如:</p><figure class="highlight jboss-cli"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs jboss-cli">vpath %<span class="hljs-string">.h</span> <span class="hljs-string">../headers</span><br></code></pre></div></td></tr></tbody></table></figure><p>make的伪目标特性可以一次生成多个可执行文件:</p><figure class="highlight stylus"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus">all : prog1 prog2 prog <span class="hljs-number">3</span><br><span class="hljs-selector-class">.PHONY</span> : all<br>prog1 : prog1<span class="hljs-selector-class">.o</span> utils<span class="hljs-selector-class">.o</span><br> cc -o prog1 prog1<span class="hljs-selector-class">.o</span> utils<span class="hljs-selector-class">.o</span><br><br>prog2 : prog2<span class="hljs-selector-class">.o</span><br> cc -o prog2 prog2<span class="hljs-selector-class">.o</span><br><br>prog3 : prog3<span class="hljs-selector-class">.o</span> sort<span class="hljs-selector-class">.o</span> utils<span class="hljs-selector-class">.o</span><br> cc -o prog3 prog3<span class="hljs-selector-class">.o</span> sort<span class="hljs-selector-class">.o</span> utils.o<br></code></pre></div></td></tr></tbody></table></figure><p>上述代码生成多个目标:prog1~3makefile的静态模式可以自动寻找target,pattern,如:</p><figure class="highlight makefile"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs makefile">objects = foo.o bar.o<br><br><span class="hljs-section">all: <span class="hljs-variable">$(objects)</span></span><br><br><span class="hljs-variable">$(objects)</span>: %.o: %.c<br> <span class="hljs-variable">$(CC)</span> -c <span class="hljs-variable">$(CFLAGS)</span> <span class="hljs-variable">$<</span> -o <span class="hljs-variable">$@</span><br></code></pre></div></td></tr></tbody></table></figure><p>上述例子等价于:</p><figure class="highlight stylus"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus">foo<span class="hljs-selector-class">.o</span> : foo<span class="hljs-selector-class">.c</span><br> $(CC) -c $(CFLAGS) foo<span class="hljs-selector-class">.c</span> -o foo<span class="hljs-selector-class">.o</span><br>bar<span class="hljs-selector-class">.o</span> : bar<span class="hljs-selector-class">.c</span><br> $(CC) -c $(CFLAGS) bar<span class="hljs-selector-class">.c</span> -o bar.o<br></code></pre></div></td></tr></tbody></table></figure><p>makefile可以自动生成.c文件对于头文件的依赖性,如:</p><figure class="highlight llvm"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs llvm"><span class="hljs-keyword">cc</span> -M main.<span class="hljs-keyword">c</span><br></code></pre></div></td></tr></tbody></table></figure><p>等价于:</p><figure class="highlight stylus"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus"><span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.o</span> : <span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.c</span> defs.h<br></code></pre></div></td></tr></tbody></table></figure><p>defs.h是main.c中包含的头文件</p><h1 id="命令">命令</h1><figure class="highlight jboss-cli"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs jboss-cli">@<span class="hljs-keyword">echo</span> 正在编译xxx模块<span class="hljs-string">...</span><br></code></pre></div></td></tr></tbody></table></figure><p>如果echo前没有@,那么会显示<code>echo 正在编译xxx模块</code>,加上@后则不会显示echo如果你希望上一条命令作用于下一条命令,那么两个命令应该在同一行且用分号分隔:</p><figure class="highlight gradle"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs gradle">cd <span class="hljs-regexp">/home/</span><span class="hljs-keyword">file</span>;pwd<br></code></pre></div></td></tr></tbody></table></figure><p>要<strong>嵌套</strong>执行maek,可以这么做:</p><figure class="highlight makefile"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs makefile"><span class="hljs-section">subsystem:</span><br> cd subdir && <span class="hljs-variable">$(MAKE)</span><br></code></pre></div></td></tr></tbody></table></figure><p>即执行subdir子目录下的makefile文件,上级的makefile变量可以传到下一级:</p><figure class="highlight dart"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs dart"><span class="hljs-keyword">export</span> <<span class="hljs-keyword">var</span>>;<br></code></pre></div></td></tr></tbody></table></figure><p>传递所有变量的话只需一个export,不需要任何变量名称</p><h1 id="变量-1">变量</h1><p>变量可以使用变量:</p><figure class="highlight makefile"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs makefile">foo=<span class="hljs-variable">$(bar)</span><br>bar=<span class="hljs-variable">$(ugh)</span><br>ugh=dsa<br><span class="hljs-section">all:</span><br> echo <span class="hljs-variable">$(foo)</span><br></code></pre></div></td></tr></tbody></table></figure><p>显示为echo dsa 需要注意的是,如果有变量这样定义:</p><figure class="highlight awk"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs awk">dir := <span class="hljs-regexp">/foo/</span>bar <span class="hljs-comment"># directory to put the frobs in</span><br></code></pre></div></td></tr></tbody></table></figure><p>那么dir的值是<code>/foo/bar</code>,后面多了四个空格</p><figure class="highlight ruby"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs ruby">foo <span class="hljs-string">?=</span> bar<br></code></pre></div></td></tr></tbody></table></figure><p>如果foo先前没有被定义,那么foo等于bar,如果foo之前有过定义,那么这条语句什么也不做。</p><h2 id="变量值的替换">变量值的替换</h2><figure class="highlight stylus"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus">foo :=<span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.o</span> <span class="hljs-selector-tag">b</span><span class="hljs-selector-class">.o</span> c<span class="hljs-selector-class">.o</span><br>bar :=$(foo:.o=.c)<br></code></pre></div></td></tr></tbody></table></figure><p>第二行把foo中的.o全部换为.c 追加变量值:</p><figure class="highlight stylus"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus">objects = <span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.o</span> foo<span class="hljs-selector-class">.o</span> bar<span class="hljs-selector-class">.o</span> utils<span class="hljs-selector-class">.o</span><br>objects += another.o<br></code></pre></div></td></tr></tbody></table></figure><h1 id="条件">条件</h1><figure class="highlight makefile"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs makefile">libs_for_gcc = -lgnu<br>normal_libs =<br><br><span class="hljs-section">foo: <span class="hljs-variable">$(objects)</span></span><br><span class="hljs-keyword">ifeq</span> (<span class="hljs-variable">$(CC)</span>,gcc)<br> <span class="hljs-variable">$(CC)</span> -o foo <span class="hljs-variable">$(objects)</span> <span class="hljs-variable">$(libs_for_gcc)</span><br><span class="hljs-keyword">else</span><br> <span class="hljs-variable">$(CC)</span> -o foo <span class="hljs-variable">$(objects)</span> <span class="hljs-variable">$(normal_libs)</span><br><span class="hljs-keyword">endif</span><br></code></pre></div></td></tr></tbody></table></figure><p>上述例子判断$(cc)是否是gcc</p><h1 id="函数">函数</h1><h2 id="subst">subst</h2><p>字符串替换,</p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml"><span class="hljs-constructor">$(<span class="hljs-params">subst</span> <span class="hljs-params">ee</span>,EE,<span class="hljs-params">feet</span> <span class="hljs-params">on</span> <span class="hljs-params">the</span> <span class="hljs-params">street</span>)</span><br></code></pre></div></td></tr></tbody></table></figure><p>把feet on the street中的ee换成EE</p><h2 id="patsubst">patsubst</h2><p>功能和subst一样,不过匹配的是模式,</p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml"><span class="hljs-constructor">$(<span class="hljs-params">patsubst</span> %.<span class="hljs-params">c</span>,%.<span class="hljs-params">o</span>,<span class="hljs-params">x</span>.<span class="hljs-params">c</span>.<span class="hljs-params">c</span> <span class="hljs-params">bar</span>.<span class="hljs-params">c</span>)</span><br></code></pre></div></td></tr></tbody></table></figure><p>把字串 x.c.c bar.c 符合模式 %.c 的单词替换成 %.o ,返回结果是 x.c.obar.o</p><h2 id="strip">strip</h2><p>去掉开头和结尾的空格</p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml"><span class="hljs-constructor">$(<span class="hljs-params">strip</span> <span class="hljs-params">a</span> <span class="hljs-params">b</span> <span class="hljs-params">c</span> )</span><br></code></pre></div></td></tr></tbody></table></figure><h2 id="findstring">findstring</h2><p>查找字符串</p><figure class="highlight reasonml"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs reasonml"><span class="hljs-constructor">$(<span class="hljs-params">findstring</span> <span class="hljs-params">a</span>,<span class="hljs-params">a</span> <span class="hljs-params">b</span> <span class="hljs-params">c</span>)</span><br></code></pre></div></td></tr></tbody></table></figure><p>返回a,如果没有,则返回空</p><h2 id="filter">filter</h2><p>过滤,返回符合模式pattern的字符串</p><figure class="highlight llvm"><table><tbody><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs llvm">sources :<span class="hljs-operator">=</span> foo.<span class="hljs-keyword">c</span> bar.<span class="hljs-keyword">c</span> baz.s ugh.h<br><span class="hljs-symbol">foo:</span> $(sources)<br> <span class="hljs-keyword">cc</span> $(<span class="hljs-keyword">filter</span> <span class="hljs-variable">%.c</span> <span class="hljs-variable">%.s</span><span class="hljs-punctuation">,</span>$(sources)) -o foo<br></code></pre></div></td></tr></tbody></table></figure><h2 id="filter-out">filter-out</h2><p>反过滤函数</p><h2 id="sort">sort</h2><p>排序</p><h2 id="word">word</h2><p>取字符串的第n个单词,如 $(word 2, foo bar baz) 返回值是 bar 。</p><h2 id="firstowrd">firstowrd</h2><p>返回字符串的第一个单词</p><p>文件名操作函数暂略</p>]]></content>
<summary type="html"><h1 id="前言">前言</h1>
<p>这几天的实验让我觉得有必要学习一下makefile 参考博客:<a href="https://seisman.github.io/how-to-write-makefile/overview.html">博客</a></p>
<bl</summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="cs" scheme="https://heeler-deer.top/tags/cs/"/>
</entry>
<entry>
<title>测试</title>
<link href="https://heeler-deer.top/posts/9daba997/"/>
<id>https://heeler-deer.top/posts/9daba997/</id>
<published>2021-08-14T12:32:33.000Z</published>
<updated>2023-06-22T01:57:22.000Z</updated>
<content type="html"><![CDATA[<h1 id="latex">latex</h1><p><span class="math display"><mjx-container class="MathJax" jax="SVG" display="true"><svg style="vertical-align: -2.827ex" xmlns="http://www.w3.org/2000/svg" width="33.872ex" height="6.785ex" role="img" focusable="false" viewBox="0 -1749.5 14971.6 2999"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(409,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path></g><g data-mml-node="mi" transform="translate(220,-686)"><path data-c="1D45A" d="M21 287Q22 293 24 303T36 341T56 388T88 425T132 442T175 435T205 417T221 395T229 376L231 369Q231 367 232 367L243 378Q303 442 384 442Q401 442 415 440T441 433T460 423T475 411T485 398T493 385T497 373T500 364T502 357L510 367Q573 442 659 442Q713 442 746 415T780 336Q780 285 742 178T704 50Q705 36 709 31T724 26Q752 26 776 56T815 138Q818 149 821 151T837 153Q857 153 857 145Q857 144 853 130Q845 101 831 73T785 17T716 -10Q669 -10 648 17T627 73Q627 92 663 193T700 345Q700 404 656 404H651Q565 404 506 303L499 291L466 157Q433 26 428 16Q415 -11 385 -11Q372 -11 364 -4T353 8T350 18Q350 29 384 161L420 307Q423 322 423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 181Q151 335 151 342Q154 357 154 369Q154 405 129 405Q107 405 92 377T69 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><rect width="1078" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(1318,0)"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(278,0)"></path></g><g data-mml-node="mo" transform="translate(2096,0)"><path data-c="2061" d=""></path></g><g data-mml-node="mi" transform="translate(2262.7,0)"><path data-c="1D436" d="M50 252Q50 367 117 473T286 641T490 704Q580 704 633 653Q642 643 648 636T656 626L657 623Q660 623 684 649Q691 655 699 663T715 679T725 690L740 705H746Q760 705 760 698Q760 694 728 561Q692 422 692 421Q690 416 687 415T669 413H653Q647 419 647 422Q647 423 648 429T650 449T651 481Q651 552 619 605T510 659Q484 659 454 652T382 628T299 572T226 479Q194 422 175 346T156 222Q156 108 232 58Q280 24 350 24Q441 24 512 92T606 240Q610 253 612 255T628 257Q648 257 648 248Q648 243 647 239Q618 132 523 55T319 -22Q206 -22 128 53T50 252Z"></path></g><g data-mml-node="mo" transform="translate(3300.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path></g><g data-mml-node="mfrac" transform="translate(4356.2,0)"><g data-mml-node="mn" transform="translate(270,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path></g><g data-mml-node="mi" transform="translate(220,-686)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path></g><rect width="800" height="60" x="120" y="220"></rect></g><g data-mml-node="mrow" transform="translate(5396.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M758 -1237T758 -1240T752 -1249H736Q718 -1249 717 -1248Q711 -1245 672 -1199Q237 -706 237 251T672 1700Q697 1730 716 1749Q718 1750 735 1750H752Q758 1744 758 1741Q758 1737 740 1713T689 1644T619 1537T540 1380T463 1176Q348 802 348 251Q348 -242 441 -599T744 -1218Q758 -1237 758 -1240Z"></path></g><g data-mml-node="munderover" transform="translate(792,0)"><g data-mml-node="mo"><path data-c="2211" d="M60 948Q63 950 665 950H1267L1325 815Q1384 677 1388 669H1348L1341 683Q1320 724 1285 761Q1235 809 1174 838T1033 881T882 898T699 902H574H543H251L259 891Q722 258 724 252Q725 250 724 246Q721 243 460 -56L196 -356Q196 -357 407 -357Q459 -357 548 -357T676 -358Q812 -358 896 -353T1063 -332T1204 -283T1307 -196Q1328 -170 1348 -124H1388Q1388 -125 1381 -145T1356 -210T1325 -294L1267 -449L666 -450Q64 -450 61 -448Q55 -446 55 -439Q55 -437 57 -433L590 177Q590 178 557 222T452 366T322 544L56 909L55 924Q55 945 60 948Z"></path></g><g data-mml-node="TeXAtom" transform="translate(148.2,-1087.9) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mo" transform="translate(345,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path></g><g data-mml-node="mn" transform="translate(1123,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path></g></g><g data-mml-node="mi" transform="translate(509.9,1150) scale(0.707)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2402.7,0)"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D44C" d="M66 637Q54 637 49 637T39 638T32 641T30 647T33 664T42 682Q44 683 56 683Q104 680 165 680Q288 680 306 683H316Q322 677 322 674T320 656Q316 643 310 637H298Q242 637 242 624Q242 619 292 477T343 333L346 336Q350 340 358 349T379 373T411 410T454 461Q546 568 561 587T577 618Q577 634 545 637Q528 637 528 647Q528 649 530 661Q533 676 535 679T549 683Q551 683 578 682T657 680Q684 680 713 681T746 682Q763 682 763 673Q763 669 760 657T755 643Q753 637 734 637Q662 632 617 587Q608 578 477 424L348 273L322 169Q295 62 295 57Q295 46 363 46Q379 46 384 45T390 35Q390 33 388 23Q384 6 382 4T366 1Q361 1 324 1T232 2Q170 2 138 2T102 1Q84 1 84 9Q84 14 87 24Q88 27 89 30T90 35T91 39T93 42T96 44T101 45T107 45T116 46T129 46Q168 47 180 50T198 63Q201 68 227 171L252 274L129 623Q128 624 127 625T125 627T122 629T118 631T113 633T105 634T96 635T83 636T66 637Z"></path></g><g data-mml-node="mi" transform="translate(614,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g></g><g data-mml-node="mo" transform="translate(1130.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z"></path></g><g data-mml-node="mfrac" transform="translate(2130.4,0)"><g data-mml-node="mn" transform="translate(409,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path></g><g data-mml-node="mi" transform="translate(220,-686)"><path data-c="1D45A" d="M21 287Q22 293 24 303T36 341T56 388T88 425T132 442T175 435T205 417T221 395T229 376L231 369Q231 367 232 367L243 378Q303 442 384 442Q401 442 415 440T441 433T460 423T475 411T485 398T493 385T497 373T500 364T502 357L510 367Q573 442 659 442Q713 442 746 415T780 336Q780 285 742 178T704 50Q705 36 709 31T724 26Q752 26 776 56T815 138Q818 149 821 151T837 153Q857 153 857 145Q857 144 853 130Q845 101 831 73T785 17T716 -10Q669 -10 648 17T627 73Q627 92 663 193T700 345Q700 404 656 404H651Q565 404 506 303L499 291L466 157Q433 26 428 16Q415 -11 385 -11Q372 -11 364 -4T353 8T350 18Q350 29 384 161L420 307Q423 322 423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 181Q151 335 151 342Q154 357 154 369Q154 405 129 405Q107 405 92 377T69 316T57 280Q55 278 41 278H27Q21 284 21 287Z"></path></g><rect width="1078" height="60" x="120" y="220"></rect></g><g data-mml-node="munderover" transform="translate(3615.1,0)"><g data-mml-node="mo"><path data-c="2211" d="M60 948Q63 950 665 950H1267L1325 815Q1384 677 1388 669H1348L1341 683Q1320 724 1285 761Q1235 809 1174 838T1033 881T882 898T699 902H574H543H251L259 891Q722 258 724 252Q725 250 724 246Q721 243 460 -56L196 -356Q196 -357 407 -357Q459 -357 548 -357T676 -358Q812 -358 896 -353T1063 -332T1204 -283T1307 -196Q1328 -170 1348 -124H1388Q1388 -125 1381 -145T1356 -210T1325 -294L1267 -449L666 -450Q64 -450 61 -448Q55 -446 55 -439Q55 -437 57 -433L590 177Q590 178 557 222T452 366T322 544L56 909L55 924Q55 945 60 948Z"></path></g><g data-mml-node="TeXAtom" transform="translate(148.2,-1087.9) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g><g data-mml-node="mo" transform="translate(345,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path></g><g data-mml-node="mn" transform="translate(1123,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"></path></g></g><g data-mml-node="mi" transform="translate(509.9,1150) scale(0.707)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5225.7,0)"><g data-mml-node="msub"><g data-mml-node="mi"><path data-c="1D44B" d="M42 0H40Q26 0 26 11Q26 15 29 27Q33 41 36 43T55 46Q141 49 190 98Q200 108 306 224T411 342Q302 620 297 625Q288 636 234 637H206Q200 643 200 645T202 664Q206 677 212 683H226Q260 681 347 681Q380 681 408 681T453 682T473 682Q490 682 490 671Q490 670 488 658Q484 643 481 640T465 637Q434 634 411 620L488 426L541 485Q646 598 646 610Q646 628 622 635Q617 635 609 637Q594 637 594 648Q594 650 596 664Q600 677 606 683H618Q619 683 643 683T697 681T738 680Q828 680 837 683H845Q852 676 852 672Q850 647 840 637H824Q790 636 763 628T722 611T698 593L687 584Q687 585 592 480L505 384Q505 383 536 304T601 142T638 56Q648 47 699 46Q734 46 734 37Q734 35 732 23Q728 7 725 4T711 1Q708 1 678 1T589 2Q528 2 496 2T461 1Q444 1 444 10Q444 11 446 25Q448 35 450 39T455 44T464 46T480 47T506 54Q523 62 523 64Q522 64 476 181L429 299Q241 95 236 84Q232 76 232 72Q232 53 261 47Q262 47 267 47T273 46Q276 46 277 46T280 45T283 42T284 35Q284 26 282 19Q279 6 276 4T261 1Q258 1 243 1T201 2T142 2Q64 2 42 0Z"></path></g><g data-mml-node="mi" transform="translate(861,-150) scale(0.707)"><path data-c="1D456" d="M184 600Q184 624 203 642T247 661Q265 661 277 649T290 619Q290 596 270 577T226 557Q211 557 198 567T184 600ZM21 287Q21 295 30 318T54 369T98 420T158 442Q197 442 223 419T250 357Q250 340 236 301T196 196T154 83Q149 61 149 51Q149 26 166 26Q175 26 185 29T208 43T235 78T260 137Q263 149 265 151T282 153Q302 153 302 143Q302 135 293 112T268 61T223 11T161 -11Q129 -11 102 10T74 74Q74 91 79 106T122 220Q160 321 166 341T173 380Q173 404 156 404H154Q124 404 99 371T61 287Q60 286 59 284T58 281T56 279T53 278T49 278T41 278H27Q21 284 21 287Z"></path></g></g></g></g><g data-mml-node="mo" transform="translate(8783.3,0) translate(0 -0.5)"><path data-c="29" d="M33 1741Q33 1750 51 1750H60H65Q73 1750 81 1743T119 1700Q554 1207 554 251Q554 -707 119 -1199Q76 -1250 66 -1250Q65 -1250 62 -1250T56 -1249Q55 -1249 53 -1249T49 -1250Q33 -1250 33 -1239Q33 -1236 50 -1214T98 -1150T163 -1052T238 -910T311 -727Q443 -335 443 251Q443 402 436 532T405 831T339 1142T224 1438T50 1716Q33 1737 33 1741Z"></path></g></g></g></g></svg></mjx-container></span></p><h1 id="nodeppt">nodeppt</h1><p>先试着插入html<br><span class="github-emoji"><span>😊</span><img src="https://github.githubassets.com/images/icons/emoji/unicode/1f60a.png?v8" srcset="/img/loading.gif" lazyload aria-hidden="true" onerror="this.parent.classList.add('github-emoji-fallback')"></span></p><iframe src="https://htmlpreview.github.io/?https://github.com/heeler-deer/absorbing/blob/main/html/dist/slide.html" width="100%" height="500" name="topFrame" scrolling="yes" noresize="noresize" frameborder="0" id="topFrame"></iframe><h1 id="视频">视频:</h1><iframe src="//player.bilibili.com/player.html?aid=847343455&bvid=BV1jL4y1e7Uz&cid=388949658&page=1" width="100%" height="500" name="topFrame" scrolling="yes" noresize="noresize" frameborder="0" id="topFrame"></iframe><h1 id="mermaid">mermaid</h1><pre><code class="mermaid" type="">graph LR 单独节点 开始 -- 带注释写法1 --> 结束 开始 -->|带注释写法2| 结束 实线开始 --- 实线结束 实线开始 --> 实线结束 实线开始 -->|带注释| 实线结束 虚线开始 -.- 虚线结束 虚线开始 -.-> 虚线结束 虚线开始 -.->|带注释| 虚线结束 粗线开始 === 粗线结束 粗线开始 ==> 粗线结束 粗线开始 ==>|带注释| 粗线结束 subgraph 子图标题 子图开始 --> 子图结束 end 节点1[方形文本框] --> 节点2{菱形文本框} 节点3(括号文本框) --> 节点4((圆形文本框))</code></pre><h1 id="label">label</h1><div class="note note-primary"> <p>文字 或者 <code>markdown</code> 均可</p> </div><div class="note note-secondary"> <p>文字 或者 <code>markdown</code> 均可</p> </div><div class="note note-success"> <p>文字 或者 <code>markdown</code> 均可</p> </div><div class="note note-danger"> <p>文字 或者 <code>markdown</code> 均可</p> </div><div class="note note-warning"> <p>文字 或者 <code>markdown</code> 均可</p> </div><div class="note note-info"> <p>文字 或者 <code>markdown</code> 均可</p> </div><div class="note note-light"> <p>文字 或者 <code>markdown</code> 均可</p> </div><h1 id="勾选框">勾选框</h1> <input type="checkbox" disabled="">text <div> <input type="checkbox" disabled="" checked="checked">text </div><h1 id="按钮">按钮</h1><a class="btn" href="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202210192107010.png" title="title" target="_blank">text</a><h1 id="组图">组图</h1><div class="group-image-container"><div class="group-image-row"><div class="group-image-wrap"><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202210192107010.png" srcset="/img/loading.gif" lazyload></div><div class="group-image-wrap"><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202210192107010.png" srcset="/img/loading.gif" lazyload></div><div class="group-image-wrap"><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202210192107010.png" srcset="/img/loading.gif" lazyload></div></div><div class="group-image-row"><div class="group-image-wrap"><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202210192107010.png" srcset="/img/loading.gif" lazyload></div><div class="group-image-wrap"><img src="https://raw.githubusercontent.com/heeler-deer/absorbing/main/png/os-1/202210192107010.png" srcset="/img/loading.gif" lazyload></div></div></div><h1 id="参考">参考</h1><p><a href="https://www.yousazoe.top/archives/f0a0db79.html">fluid写作指南</a></p>]]></content>
<summary type="html"><h1 id="latex">latex</h1>
<p><span class="math display"><mjx-container class="MathJax" jax="SVG" display="true"><svg style="vertical-align: </summary>
<category term="blog" scheme="https://heeler-deer.top/categories/blog/"/>
<category term="花里胡哨" scheme="https://heeler-deer.top/tags/%E8%8A%B1%E9%87%8C%E8%83%A1%E5%93%A8/"/>
</entry>
</feed>