-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlab2.html
More file actions
128 lines (127 loc) · 45.4 KB
/
Copy pathlab2.html
File metadata and controls
128 lines (127 loc) · 45.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="VuePress 2.0.0-rc.14">
<script>
(function() {
const userMode = localStorage.getItem('vuepress-reco-color-scheme') || 'auto';
const systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
if (userMode === 'dark' || (userMode === 'auto' && systemDarkMode)) {
document.documentElement.classList.toggle('dark', true);
}
})();
</script>
<title>Lab2实验报告 | Yunge Hu 's Blog</title><meta name="description" content="Just playing around">
<link rel="preload" href="/assets/style-DFiSfBVn.css" as="style"><link rel="stylesheet" href="/assets/style-DFiSfBVn.css">
<link rel="modulepreload" href="/assets/app-B51tXhJU.js"><link rel="modulepreload" href="/assets/lab2.html-gAWXyUFt.js">
<link rel="prefetch" href="/assets/timeline.html-CDRCyYXN.js" as="script"><link rel="prefetch" href="/assets/posts.html-Cm3Bj9S1.js" as="script"><link rel="prefetch" href="/assets/friendship-link.html-CPYWbDf2.js" as="script"><link rel="prefetch" href="/assets/1.html-BvGA5exa.js" as="script"><link rel="prefetch" href="/assets/1.html-CQiPtbSY.js" as="script"><link rel="prefetch" href="/assets/1.html-B91OJGi4.js" as="script"><link rel="prefetch" href="/assets/1.html-Tfqc0eqa.js" as="script"><link rel="prefetch" href="/assets/1.html-DkR1aWCw.js" as="script"><link rel="prefetch" href="/assets/1.html-9JnLqyKk.js" as="script"><link rel="prefetch" href="/assets/2.html-Bgp2cdo4.js" as="script"><link rel="prefetch" href="/assets/3.html-BrEt4hPg.js" as="script"><link rel="prefetch" href="/assets/index.html-BKyJy_kV.js" as="script"><link rel="prefetch" href="/assets/Install-Neo4j-in-Ubuntu-and-Use-Gremlin.html-D3zJqoKu.js" as="script"><link rel="prefetch" href="/assets/Neo4j.html-RU17f5ie.js" as="script"><link rel="prefetch" href="/assets/index.html-DTD_Tf27.js" as="script"><link rel="prefetch" href="/assets/README.zh.html-C95KaJWV.js" as="script"><link rel="prefetch" href="/assets/Javajibenchengxushejijiegou.html-Cop84p5k.js" as="script"><link rel="prefetch" href="/assets/Javamianxiangduixiangchengxusheji——duixiangyulei.html-RHrWrJ8D.js" as="script"><link rel="prefetch" href="/assets/Javamianxiangduixiangchengxusheji——jiekou、lambdabiaodashiyunabulei.html-B4BIhUeh.js" as="script"><link rel="prefetch" href="/assets/Javamianxiangduixiangchengxusheji——jicheng.html-CDNHmPwq.js" as="script"><link rel="prefetch" href="/assets/bingfa.html-BObwH6f-.js" as="script"><link rel="prefetch" href="/assets/yichangduanyanherizhi.html-Bw2Q646T.js" as="script"><link rel="prefetch" href="/assets/fanxingyujihe.html-ChyCepcN.js" as="script"><link rel="prefetch" href="/assets/index.html-B_tI2L4g.js" as="script"><link rel="prefetch" href="/assets/suoyincaozuo.html-M9SgPFiv.js" as="script"><link rel="prefetch" href="/assets/lab0.html-DQt1B-xd.js" as="script"><link rel="prefetch" href="/assets/lab1.html-Dvm30kLN.js" as="script"><link rel="prefetch" href="/assets/lab3.html-LQVGolsr.js" as="script"><link rel="prefetch" href="/assets/lab4.html-CF_2B461.js" as="script"><link rel="prefetch" href="/assets/lab5.html-2WxLf5I9.js" as="script"><link rel="prefetch" href="/assets/lab6.html-ueb45YH9.js" as="script"><link rel="prefetch" href="/assets/index.html-CjBzVZj0.js" as="script"><link rel="prefetch" href="/assets/404.html-Dk0UZDtj.js" as="script"><link rel="prefetch" href="/assets/Valine.min-Dm4Ijz6H.js" as="script"><link rel="prefetch" href="/assets/giscus-2a044aea-CdPDkb7_.js" as="script">
</head>
<body>
<div id="app"><!--[--><div class="theme-container series--no show-catalog"><header class="navbar-container not-open"><div class="navbar-inner"><div class="site-brand nav-item"><img class="logo" src="/logo.png" alt="Yunge Hu 's Blog"><a href="/" class="site-name can-hide">Yunge Hu 's Blog</a></div><div class="nav-item navbar-links-wrapper" style=""><div><form class="search-box" role="search"><input type="search" autocomplete="off" spellcheck="false" value><!----></form></div><nav class="navbar-links"><!--[--><div class="navbar-links__item"><a href="/" class="link router-link-active" aria-label="Home"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Home<!--]--></span></span><!--[--><!--]--></a></div><div class="navbar-links__item"><a class="link" href="https://github.com/gitDebuger/gitdebuger.github.io" target="_blank" rel="noopener noreferrer" aria-label="GitHub"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->GitHub<!--]--></span></span><span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!--[--><!--]--></a></div><!--]--></nav><span class="xicon-container btn-toggle-dark-mode btn--dark-mode"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M15 2h2v3h-2z" fill="currentColor"></path><path d="M27 15h3v2h-3z" fill="currentColor"></path><path d="M15 27h2v3h-2z" fill="currentColor"></path><path d="M2 15h3v2H2z" fill="currentColor"></path><path d="M5.45 6.884l1.414-1.415l2.121 2.122l-1.414 1.414z" fill="currentColor"></path><path d="M23 7.58l2.121-2.12l1.414 1.414l-2.121 2.121z" fill="currentColor"></path><path d="M23.002 24.416l1.415-1.414l2.12 2.122l-1.413 1.414z" fill="currentColor"></path><path d="M5.47 25.13L7.59 23L9 24.42l-2.12 2.12l-1.41-1.41z" fill="currentColor"></path><path d="M16 8a8 8 0 1 0 8 8a8 8 0 0 0-8-8zm0 14a6 6 0 0 1 0-12z" fill="currentColor"></path></svg></span><span class="xicon-container btn-toggle-menus"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" style="width:20px;height:20px;font-size:20px;color:inherit;"><circle cx="16" cy="8" r="2" fill="currentColor"></circle><circle cx="16" cy="16" r="2" fill="currentColor"></circle><circle cx="16" cy="24" r="2" fill="currentColor"></circle></svg></span></div></div></header><!----><!----><!----><!--[--><main class="page-container"><aside class="series-container"><!--[--><!--]--></aside><div class="page-content"><h1 class="page-title">Lab2实验报告</h1><div class="page-info"><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M16 4a5 5 0 1 1-5 5a5 5 0 0 1 5-5m0-2a7 7 0 1 0 7 7a7 7 0 0 0-7-7z" fill="currentColor"></path><path d="M26 30h-2v-5a5 5 0 0 0-5-5h-6a5 5 0 0 0-5 5v5H6v-5a7 7 0 0 1 7-7h6a7 7 0 0 1 7 7z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Yunge Hu<!--]--></span></span><!----><span class="xicon-container left"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:18px;height:18px;font-size:18px;color:inherit;"><path d="M11.17 6l3.42 3.41l.58.59H28v16H4V6h7.17m0-2H4a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2H16l-3.41-3.41A2 2 0 0 0 11.17 4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[--><!--[--><a href="/categories/OS/1.html" class="">OS</a><!--]--><!--]--></span></span><!----><!----></div><div class="theme-reco-md-content"><div><h1 id="lab2实验报告" tabindex="-1"><a class="header-anchor" href="#lab2实验报告"><span>Lab2实验报告</span></a></h1><h2 id="_1-思考题" tabindex="-1"><a class="header-anchor" href="#_1-思考题"><span>1. 思考题</span></a></h2><h3 id="_1-1-thinking-2-1" tabindex="-1"><a class="header-anchor" href="#_1-1-thinking-2-1"><span>1.1 Thinking 2.1</span></a></h3><p><strong>在编写的C程序中,指针变量中存储的地址被视为虚拟地址还是物理地址?</strong></p><p><strong>MIPS汇编程序中 <code>lw</code> 和 <code>sw</code> 指令使用的地址被视为虚拟地址还是物理地址?</strong></p><p>虚拟地址还是物理地址与所使用的编程语言没有关系,不管是C语言这种高级语言还是汇编语言,其中的地址是虚拟地址还是物理地址只取决于程序的运行环境。</p><p>对于运行在具有虚拟内存管理机制的操作系统上的程序,其中的地址是虚拟地址;对于运行在stm32这种单片机上的嵌入式程序而言,由于硬件本身的内存空间很小,也没有大量的程序需要运行,往往只有一个程序运行在单片机上,这时使用虚拟内存机制没有任何意义,此时的地址就是物理地址。</p><p>所以,程序中的地址究竟是虚拟地址还是物理地址,需要结合实际情况进行分析,与使用的编程语言无关。</p><h3 id="_1-2-thinking-2-2" tabindex="-1"><a class="header-anchor" href="#_1-2-thinking-2-2"><span>1.2 Thinking 2.2</span></a></h3><ul><li><strong>从可重用性的角度,阐述用宏来实现链表的好处。</strong></li><li><strong>查看实验环境中的 <code>/usr/include/sys/queue.h</code> ,了解其中单向链表与循环链表的实现,比较它们与本实验中使用的双向链表,分析三者在插入与删除操作上的性能差异。</strong></li></ul><p>由于C语言不具有泛型机制,所以为了在其中达到泛型的效果,必须通过宏。从而在这里使用宏实现链表的优点,就变成了使用泛型类和泛型函数实现链表的优点。所以使用宏实现链表的优点如下:</p><ol><li>泛型性:宏可以根据不同的数据类型生成相应的代码,使得链表可以存储任意类型的数据,实现了泛型能力。</li><li>灵活性:通过宏定义链表操作函数,可以在不同的程序中轻松地使用相同的链表实现,而无需为每种数据类型编写不同的链表代码。</li><li>简化代码:使用宏可以减少重复的代码量,提高代码的可读性和可维护性。相比于手动编写针对不同数据类型的链表实现,使用宏可以减少冗余代码,简化链表操作函数的编写。</li><li>易于维护:通过宏定义的链表操作函数,可以集中管理链表的逻辑,当需要修改链表操作时,只需修改宏定义即可,而不必修改多处代码。</li><li>提高效率:使用宏定义链表操作函数可以将一些常用的操作优化为内联代码,提高程序的执行效率。</li></ol><p>相对于单向链表和循环链表,双向链表在插入与删除操作上具有以下优势:</p><ol><li>在保证 $O(1)$ 时间复杂度的前提下,双向链表中可以在任意位置进行前插和后插操作,即在某个节点之前或之后插入新节点,而不仅仅局限于在链表头部或尾部插入节点。这使得双向链表更加灵活,可以更方便地实现特定的插入需求。</li><li>对于已知节点的情况下,双向链表的删除操作效率更高。因为双向链表中的节点包含指向前一个节点和后一个节点的指针,所以在删除某个节点时,可以直接修改其前一个节点和后一个节点的指针,而不需要像单向链表那样需要遍历找到前一个节点。这使得双向链表的删除操作更加高效。</li></ol><h3 id="_1-3-thinking-2-3" tabindex="-1"><a class="header-anchor" href="#_1-3-thinking-2-3"><span>1.3 Thinking 2.3</span></a></h3><p><strong>请阅读 <code>include/queue.h</code> 以及 <code>include/pmap.h</code> , 将 <code>Page_list</code> 的结构梳理清楚,选择正确的展开结构。</strong></p><p>首先,有下面的三个定义:</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name function">LIST_ENTRY</span><span class="token expression"><span class="token punctuation">(</span>type<span class="token punctuation">)</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token keyword">struct</span> <span class="token punctuation">{</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token keyword">struct</span> <span class="token class-name">type</span> <span class="token operator">*</span>le_next<span class="token punctuation">;</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token keyword">struct</span> <span class="token class-name">type</span> <span class="token operator">*</span><span class="token operator">*</span>le_prev<span class="token punctuation">;</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token punctuation">}</span></span></span></span>
<span class="line"><span class="token keyword">typedef</span> <span class="token function">LIST_ENTRY</span><span class="token punctuation">(</span>Page<span class="token punctuation">)</span> Page_LIST_entry_t<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token punctuation">{</span></span>
<span class="line"> Page_LIST_entry_t pp_link<span class="token punctuation">;</span></span>
<span class="line"> u_short pp_ref<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以得出 <code>Page</code> 结构体的展开如下:</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span>le_next<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span><span class="token operator">*</span>le_prev<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span> pp_link<span class="token punctuation">;</span></span>
<span class="line"> u_short pp_ref<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>进而再结合下面的宏定义和宏的调用:</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name function">LIST_HEAD</span><span class="token expression"><span class="token punctuation">(</span>name<span class="token punctuation">,</span> type<span class="token punctuation">)</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token keyword">struct</span> <span class="token class-name">name</span> <span class="token punctuation">{</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token keyword">struct</span> <span class="token class-name">type</span> <span class="token operator">*</span>lh_first<span class="token punctuation">;</span> </span><span class="token punctuation">\</span></span>
<span class="line"> <span class="token expression"><span class="token punctuation">}</span></span></span></span>
<span class="line"><span class="token function">LIST_HEAD</span><span class="token punctuation">(</span>Page_list<span class="token punctuation">,</span> Page<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以得出 <code>Page_list</code> 结构体的定义:</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">struct</span> <span class="token class-name">Page_list</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span>lh_first<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>从而 <code>Page_list</code> 结构体的展开如下:</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">struct</span> <span class="token class-name">Page_list</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span>le_next<span class="token punctuation">;</span></span>
<span class="line"> <span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span><span class="token operator">*</span>le_prev<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span> pplink<span class="token punctuation">;</span></span>
<span class="line"> u_short pp_ref<span class="token punctuation">;</span></span>
<span class="line"> <span class="token punctuation">}</span> <span class="token operator">*</span>lh_first<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>所以,应该选择题目中的 C 选项。</p><h3 id="_1-4-thinking-2-4" tabindex="-1"><a class="header-anchor" href="#_1-4-thinking-2-4"><span>1.4 Thinking 2.4</span></a></h3><ul><li><strong>请阅读上面有关TLB的描述,从虚拟内存和多进程操作系统的实现角度,阐述ASID的必要性。</strong></li><li><strong>请阅读MIPS 4Kc文档《MIPS32® 4K™ Processor Core Family Software User’s Manual》的Section 3.3.1与Section 3.4,结合ASID段的位数,说明4Kc中可容纳不同的地址空间的最大数量。</strong></li></ul><p>ASID是一个用于标识进程地址空间的唯一标识符。在多进程操作系统中,每个进程都有自己的地址空间,包括代码、数据和堆栈等。</p><p>ASID在TLB中的必要性主要体现在以下几个方面:</p><ol><li>**隔离进程地址空间:**在多进程环境中,不同的进程具有不同的地址空间,因此需要确保TLB中缓存的虚拟地址到物理地址的映射关系是针对特定进程的。通过为每个进程分配独立的ASID,可以将TLB的缓存划分为多个部分,确保不同进程之间的地址映射不会互相干扰,从而实现进程间的地址空间隔离。</li><li>**提高TLB的效率:**如果TLB中不使用ASID来区分不同的地址空间,那么在进程切换时,必须将TLB中的所有条目都清空,以防止新进程使用之前进程的地址映射。这样做会降低TLB的命中率,影响系统性能。而使用ASID可以使TLB中的条目与进程关联,进程切换时只需要刷新与当前进程相关的TLB条目,可以减少TLB刷新的开销,提高TLB的命中率和整体系统性能。</li><li>**简化地址转换逻辑:**在硬件实现中,TLB的地址转换逻辑需要根据当前虚拟地址和ASID来查找对应的物理地址。有了ASID,可以简化TLB的查找逻辑,只需在TLB查找时同时匹配虚拟地址和ASID即可,而不必考虑多个进程之间的地址映射关系。</li></ol><p>在MIPS 4Kc中,ASID字段的位数通常是 $8$ 位。这意味着可以有 $2^8=256$ 个不同的ASID。但是由于TLB的大小是固定的,因此可以容纳的不同地址空间的最大数量受到TLB的大小限制。根据MIPS 4Kc文档中Section 3.3.1和Section 3.4的描述,MIPS 4Kc中的TLB共有 $64$ 个条目。每个TLB条目可以映射一个虚拟地址到一个物理地址。</p><p>综上所述,MIPS 4Kc中可以容纳的不同地址空间的最大数量受到TLB条目的数量限制,即 $64$ 个。因此,即使ASID有 $256$ 个不同的取值,但实际上,MIPS 4Kc可以同时支持的不同地址空间的最大数量仍然是 $64$ 个,这是由TLB的大小所决定的。</p><h3 id="_1-5-thinking-2-5" tabindex="-1"><a class="header-anchor" href="#_1-5-thinking-2-5"><span>1.5 Thinking 2.5</span></a></h3><p><strong>请回答下述三个问题:</strong></p><ul><li><strong><code>tlb_invalidate</code> 和 <code>tlb_out</code> 的调用关系?</strong></li><li><strong>请用一句话概括 <code>tlb_invalidate</code> 的作用。</strong></li><li><strong>逐行解释 <code>tlb_out</code> 中的汇编代码。</strong></li></ul><p>C语言源代码文件 <code>tlbex.c</code> 中的 <code>tlb_invalidate</code> 函数会调用MIPS汇编文件 <code>tlb_asm.S</code> 中的叶函数 <code>tlb_out</code> 。</p><p>函数 <code>tlb_invalidate</code> 的作用是:在更新页表项后被调用,以将给定虚拟地址 <code>va</code> 和标识符 <code>asid</code> 对应的TLB表项无效化,从而使得在下一次访问该虚拟地址时会触发TLB重填异常,使得操作系统对TLB进行重填。</p><p>逐行解释 <code>tlb_out</code> 中的汇编代码:</p><div class="language-assembly line-numbers-mode" data-highlighter="prismjs" data-ext="assembly" data-title="assembly"><pre class="language-assembly"><code><span class="line">/* 定义函数入口点即函数的标签 */</span>
<span class="line">/* 这里定义了一个名为 tlb_out 的函数 */</span>
<span class="line">LEAF(tlb_out)</span>
<span class="line">/* 告诉汇编器禁止对指令重新排序 */</span>
<span class="line">/* 确保在后续的代码中指令的顺序不会被改变。 */</span>
<span class="line">.set noreorder</span>
<span class="line"> /* 将协处理器 0 中寄存器 CP0_ENTRYHI 中的数据写入到通用寄存器 t0 中 */</span>
<span class="line"> mfc0 t0, CP0_ENTRYHI</span>
<span class="line"> /* 将通用寄存器 a0 中的数据写入到协处理器 0 中寄存器 CP0_ENTRYHI 中 */</span>
<span class="line"> mtc0 a0, CP0_ENTRYHI</span>
<span class="line"> /* 添加空指令避免数据冲突 */</span>
<span class="line"> nop</span>
<span class="line"> /* Step 1: Use 'tlbp' to probe TLB entry */</span>
<span class="line"> /* Exercise 2.8: Your code here. (1/2) */</span>
<span class="line"> /* 根据 EntryHi 寄存器中的 Key 值查找 TLB 中对应表项 */</span>
<span class="line"> /* 并将表项的索引存入 Index 寄存器 */</span>
<span class="line"> tlbp</span>
<span class="line"> /* 添加空指令避免数据冲突 */</span>
<span class="line"> nop</span>
<span class="line"> /* Step 2: Fetch the probe result from CP0.Index */</span>
<span class="line"> /* 将协处理器 0 中寄存器 CP0_INDEX 中的数据写入到通用寄存器 t1 中 */</span>
<span class="line"> /* 也就是将表项索引从寄存器 CP0_INDEX 存入寄存器 t1 中 */</span>
<span class="line"> mfc0 t1, CP0_INDEX</span>
<span class="line">/* 告诉汇编器恢复对指令的重新排序 */</span>
<span class="line">.set reorder</span>
<span class="line"> /* 如果 t1 的值小于零则跳转到标签 NO_SUCH_ENTRY 处执行 */</span>
<span class="line"> /* 这里用于检查 TLB 查询结果是否为无效 */</span>
<span class="line"> /* 即没有匹配的 TLB 表项 */</span>
<span class="line"> bltz t1, NO_SUCH_ENTRY</span>
<span class="line">/* 告诉汇编器禁止对指令重新排序 */</span>
<span class="line">.set noreorder</span>
<span class="line"> /* 如果存在对应的表项执行无效化操作 */</span>
<span class="line"> /* 清空 CP0 中的 ENTRYHI ENTRYLO0 和 ENTRYLO1 寄存器 */</span>
<span class="line"> /* 相当于将这些寄存器中的内容置零 */</span>
<span class="line"> mtc0 zero, CP0_ENTRYHI</span>
<span class="line"> mtc0 zero, CP0_ENTRYLO0</span>
<span class="line"> mtc0 zero, CP0_ENTRYLO1</span>
<span class="line"> /* 插入空指令避免数据冲突 */</span>
<span class="line"> nop</span>
<span class="line"> /* Step 3: Use 'tlbwi' to write CP0.EntryHi/Lo into TLB at CP0.Index */</span>
<span class="line"> /* Exercise 2.8: Your code here. (2/2) */</span>
<span class="line"> /* 以 Index 寄存器中的值为索引将 EntryHi 与 EntryLo 中的数据写入到 TLB 中对应表项 */</span>
<span class="line"> tlbwi</span>
<span class="line">/* 告诉汇编器恢复对指令的重新排序 */</span>
<span class="line">.set reorder</span>
<span class="line">/* 定义了一个标签 */</span>
<span class="line">/* 用于表示如果不存在匹配的 TLB 表项时跳转到的位置 */</span>
<span class="line">NO_SUCH_ENTRY:</span>
<span class="line"> /* 将通用寄存器 t0 的内容写入到协处理器 0 中的寄存器 CP0_ENTRYHI 中 */</span>
<span class="line"> /* 相当于恢复寄存器 CP0_ENTRYHI 的值 */</span>
<span class="line"> mtc0 t0, CP0_ENTRYHI</span>
<span class="line"> /* 无条件跳转指令 */</span>
<span class="line"> /* 用于跳转到寄存器 ra 中保存的返回地址 */</span>
<span class="line"> /* 用于函数返回 */</span>
<span class="line"> j ra</span>
<span class="line">/* 定义函数的结束点 */</span>
<span class="line">END(tlb_out)</span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="_1-6-thinking-2-6" tabindex="-1"><a class="header-anchor" href="#_1-6-thinking-2-6"><span>1.6 Thinking 2.6</span></a></h3><p><strong>从下述三个问题中任选其一回答:</strong></p><ol><li><strong>简单了解并叙述x86体系结构中的内存管理机制,比较x86和MIPS在内存管理上的区别。</strong></li><li><strong>简单了解并叙述RISC-V中的内存管理机制,比较RISC-V与MIPS在内存管理上的区别。</strong></li><li><strong>简单了解并叙述LoongArch中的内存管理机制,比较LoongArch与MIPS在内存管理上的区别。</strong></li></ol><p>在x86体系结构中,内存管理主要通过分段和分页来实现。分段将物理内存划分为不同的段,每个段有自己的基址和界限,用于实现逻辑地址到线性地址的转换。分页通过页表将线性地址映射到物理地址,实现了虚拟地址到物理地址的转换。x86体系结构还支持虚拟内存和页面置换机制,以及特权级别的保护机制。</p><p>与MIPS相比,x86体系结构采用了较为复杂的分段机制,其中包括全局描述符表、局部描述符表等。而MIPS主要采用分页机制,对内存管理相对简单。此外,x86体系结构在内存管理方面提供了更多的特性和功能,如分页级别的保护、支持大页、内存类型等,使其在内存管理方面更加灵活和强大。</p><h2 id="_2-难点分析" tabindex="-1"><a class="header-anchor" href="#_2-难点分析"><span>2. 难点分析</span></a></h2><h3 id="_2-1-内存分配与管理" tabindex="-1"><a class="header-anchor" href="#_2-1-内存分配与管理"><span>2.1 内存分配与管理</span></a></h3><p>内存分配与管理的相关函数主要位于 <code>kern/pmap.c</code> 中,其中包括可用物理空间的探测、建立页式管理机制之前的内存分配、页式管理机制初始化、页面申请、页面回收、页面寻找等。这些函数是整个页面管理机制的核心,需要读懂每个函数的功能才能理解整个内存分配与管理机制。</p><div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c" data-title="c"><pre class="language-c"><code><span class="line"><span class="token keyword">void</span> <span class="token function">mips_detect_memory</span><span class="token punctuation">(</span>u_int _memsize<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">void</span> <span class="token operator">*</span><span class="token function">alloc</span><span class="token punctuation">(</span>u_int n<span class="token punctuation">,</span> u_int align<span class="token punctuation">,</span> <span class="token keyword">int</span> clear<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">void</span> <span class="token function">mips_vm_init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">void</span> <span class="token function">page_init</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">int</span> <span class="token function">page_alloc</span><span class="token punctuation">(</span><span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span><span class="token operator">*</span>new<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">void</span> <span class="token function">page_free</span><span class="token punctuation">(</span><span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span>pp<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">pgdir_walk</span><span class="token punctuation">(</span>Pde <span class="token operator">*</span>pgdir<span class="token punctuation">,</span> u_long va<span class="token punctuation">,</span> <span class="token keyword">int</span> create<span class="token punctuation">,</span> Pte <span class="token operator">*</span><span class="token operator">*</span>ppte<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">int</span> <span class="token function">page_insert</span><span class="token punctuation">(</span>Pde <span class="token operator">*</span>pgdir<span class="token punctuation">,</span> u_int asid<span class="token punctuation">,</span> <span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span>pp<span class="token punctuation">,</span> u_long va<span class="token punctuation">,</span> u_int perm<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span><span class="token function">page_lookup</span><span class="token punctuation">(</span>Pde <span class="token operator">*</span>pgdir<span class="token punctuation">,</span> u_long va<span class="token punctuation">,</span> Pte <span class="token operator">*</span><span class="token operator">*</span>ppte<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">void</span> <span class="token function">page_decref</span><span class="token punctuation">(</span><span class="token keyword">struct</span> <span class="token class-name">Page</span> <span class="token operator">*</span>pp<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">void</span> <span class="token function">page_remove</span><span class="token punctuation">(</span>Pde <span class="token operator">*</span>pgdir<span class="token punctuation">,</span> u_int asid<span class="token punctuation">,</span> u_long va<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>以上就是内存管理机制的核心函数。</p><h3 id="_2-2-链表宏" tabindex="-1"><a class="header-anchor" href="#_2-2-链表宏"><span>2.2 链表宏</span></a></h3><p>在 <code>include/queue.h</code> 中使用宏实现了泛型的双向链表。</p><p>由于C语言本身不支持泛型,需要通过宏模拟,会使得代码略显晦涩。另外,这里的双向链表不同于常规的双向链表,它的前向指针实际上是指向了前一个链表节点的指针域,也就是<strong>指向了"指向自己的指针"的指针</strong>。</p><p>理解了这一点后,就能理解这个文件中对于双向链表的实现原理了。</p><h3 id="_2-3-tlb" tabindex="-1"><a class="header-anchor" href="#_2-3-tlb"><span>2.3 TLB</span></a></h3><p>TLB结构和操作流程比较复杂,同时MIPS的TLB使用了奇偶页的设计,使得其更加难以理解。</p><p>主要操作函数位于 <code>kern/tlbex.c</code> 和 <code>kern/tlb_asm.S</code> 中,其中C语言代码包括的功能有TLB无效化、被动页面分配和TLB重填等功能。</p><p>汇编语言中,主要涉及对三个寄存器的操作以及几个特殊的TLB操作指令。</p><h2 id="_3-实验体会" tabindex="-1"><a class="header-anchor" href="#_3-实验体会"><span>3. 实验体会</span></a></h2><p>操作系统实验涉及的概念和程序代码较多,一定要读懂理解整个工程项目的代码,才能完成好每一次实验。</p><p>另外,限时测试中需要编写的代码和已有的代码结构很相似,了解原有代码的实现方式有助于在限时测试中完成代码的编写。</p></div></div><footer class="page-meta"><div class="meta-item edit-link"><span class="xicon-container left meta-item-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M2 26h28v2H2z" fill="currentColor"></path><path d="M25.4 9c.8-.8.8-2 0-2.8l-3.6-3.6c-.8-.8-2-.8-2.8 0l-15 15V24h6.4l15-15zm-5-5L24 7.6l-3 3L17.4 7l3-3zM6 22v-3.6l10-10l3.6 3.6l-10 10H6z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Edit this page<!--]--></span></span></div><div class="meta-item last-updated"><span class="xicon-container left meta-item-label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" class="xicon-icon" style="width:20px;height:20px;font-size:20px;color:inherit;"><path d="M26 4h-4V2h-2v2h-8V2h-2v2H6c-1.1 0-2 .9-2 2v20c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 22H6V12h20v14zm0-16H6V6h4v2h2V6h8v2h2V6h4v4z" fill="currentColor"></path></svg><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->Last Updated 2024/9/22 16:35:40<!--]--></span></span></div></footer><!----><!----></div><div class="page-catalog-container"><h5 class="tip">ON THIS PAGE</h5><ul><!--[--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/OS/lab2.html#_1-思考题" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1. 思考题"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1. 思考题<!--]--></span></span><!--[--><!--]--></a></li><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_1-1-thinking-2-1" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.1 Thinking 2.1"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.1 Thinking 2.1<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_1-2-thinking-2-2" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.2 Thinking 2.2"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.2 Thinking 2.2<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_1-3-thinking-2-3" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.3 Thinking 2.3"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.3 Thinking 2.3<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_1-4-thinking-2-4" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.4 Thinking 2.4"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.4 Thinking 2.4<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_1-5-thinking-2-5" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.5 Thinking 2.5"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.5 Thinking 2.5<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_1-6-thinking-2-6" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="1.6 Thinking 2.6"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->1.6 Thinking 2.6<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/OS/lab2.html#_2-难点分析" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="2. 难点分析"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2. 难点分析<!--]--></span></span><!--[--><!--]--></a></li><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_2-1-内存分配与管理" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="2.1 内存分配与管理"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2.1 内存分配与管理<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_2-2-链表宏" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="2.2 链表宏"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2.2 链表宏<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--[--><li class="page-catalog-menu-depth_3"><a aria-current="page" href="/blogs/OS/lab2.html#_2-3-tlb" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="2.3 TLB"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->2.3 TLB<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--><!--[--><li class="page-catalog-menu-depth_2"><a aria-current="page" href="/blogs/OS/lab2.html#_3-实验体会" class="router-link-active router-link-exact-active link page-catalog-item page-catalog-item" aria-label="3. 实验体会"><!--[--><!--]--><span class="xicon-container left"><!--[--><!----><!--]--><span class="xicon-content" style="color:inherit;font-size:14px;"><!--[-->3. 实验体会<!--]--></span></span><!--[--><!--]--></a></li><!--]--><!--]--></ul></div></main><!--]--></div><!--[--><!----><!----><!--]--><!--]--></div>
<script type="module" src="/assets/app-B51tXhJU.js" defer></script>
</body>
</html>