ucore_os_docs/lab3.htm

2047 lines
155 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html>
<head>
<meta name=标题 content="实验二:内存管理">
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<meta name=Generator content="Microsoft Word 14 (filtered)">
<title>实验二:内存管理</title>
<style>
<!--
/* Font Definitions */
@font-face
{font-family:Arial;
panose-1:2 11 6 4 2 2 2 2 2 4;}
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"Lucida Sans";
panose-1:2 11 6 2 3 5 4 2 2 4;}
@font-face
{font-family:楷体;
panose-1:2 1 6 9 6 1 1 1 1 1;}
@font-face
{font-family:"\@楷体";
panose-1:2 1 6 9 6 1 1 1 1 1;}
@font-face
{font-family:永中宋体;
panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"\@永中宋体";
panose-1:0 0 0 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-size:10.5pt;
font-family:"Times New Roman";}
h1
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:12.0pt;
margin-left:21.25pt;
text-align:center;
text-indent:-6.85pt;
line-height:12.0pt;
font-size:12.0pt;
font-family:;
font-weight:bold;}
h2
{margin-top:6.0pt;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:63.8pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:-49.6pt;
font-size:15.0pt;
font-family:Arial;
font-weight:bold;}
h3
{margin-top:13.0pt;
margin-right:0cm;
margin-bottom:13.0pt;
margin-left:70.9pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:-70.9pt;
line-height:172%;
font-size:14.0pt;
font-family:"Times New Roman";
font-weight:bold;}
h4
{margin-top:14.0pt;
margin-right:0cm;
margin-bottom:14.5pt;
margin-left:21.0pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:-21.0pt;
font-size:10.5pt;
font-family:"Times New Roman";
font-weight:bold;}
p.MsoNormalIndent, li.MsoNormalIndent, div.MsoNormalIndent
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:10.0pt;
font-size:10.5pt;
font-family:"Times New Roman";}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{margin:0cm;
margin-bottom:.0001pt;
text-align:center;
layout-grid-mode:char;
border:none;
padding:0cm;
font-size:9.0pt;
font-family:"Times New Roman";}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{margin:0cm;
margin-bottom:.0001pt;
layout-grid-mode:char;
font-size:9.0pt;
font-family:"Times New Roman";}
p.MsoBodyText, li.MsoBodyText, div.MsoBodyText
{margin-top:0cm;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:0cm;
text-align:justify;
text-justify:inter-ideograph;
font-size:10.5pt;
font-family:"Times New Roman";}
p.MsoDocumentMap, li.MsoDocumentMap, div.MsoDocumentMap
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
background:navy;
font-size:10.5pt;
font-family:"Times New Roman";}
p
{margin-right:0cm;
margin-left:0cm;
font-size:12.0pt;
font-family:;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-size:9.0pt;
font-family:"Times New Roman";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
text-indent:21.0pt;
font-size:10.5pt;
font-family:"Times New Roman";}
span.a1
{font-family:"Lucida Sans";}
span.1
{font-family:;
font-weight:bold;}
span.2
{font-family:Arial;
font-weight:bold;}
span.3
{font-family:"Lucida Sans";
font-weight:bold;}
span.4
{font-family:"Lucida Sans";
font-weight:bold;}
.MsoChpDefault
{font-size:10.0pt;}
/* Page Definitions */
@page WordSection1
{size:596.0pt 842.0pt;
margin:36.0pt 36.0pt 36.0pt 36.0pt;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style>
</head>
<body lang=EN-US>
<div class=WordSection1>
<p class=MsoNormal align=left style='margin-left:164.0pt;text-align:left;
line-height:23.6pt;text-autospace:none'><span lang=ZH-CN style='font-size:16.0pt;
font-family:楷体;vertical-align:sub;letter-spacing:.05pt'></span><span
lang=ZH-CN style='font-size:16.0pt;font-family:楷体;vertical-align:sub;
letter-spacing:.1pt'>验三</span><span lang=ZH-CN style='font-size:16.0pt;
font-family:楷体;vertical-align:sub;letter-spacing:.05pt'></span><span
lang=ZH-CN style='font-size:16.0pt;font-family:楷体;vertical-align:sub;
letter-spacing:.1pt'>虚拟内存管</span><span lang=ZH-CN style='font-size:16.0pt;
font-family:楷体;vertical-align:sub'></span></p>
<p class=MsoNormal align=left style='margin-left:5.7pt;text-align:left;
text-autospace:none'><b><span style='font-size:17.0pt'>1    </span></b><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体;letter-spacing:.05pt'>实验目</span><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体'></span></p>
<p class=MsoListParagraph align=left style='margin-left:41.15pt;text-align:
left;text-indent:-18.0pt;text-autospace:none'><span style='font-size:12.0pt;
letter-spacing:.05pt'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体;
letter-spacing:.05pt'>了解虚拟内存的</span><span style='font-size:12.0pt;letter-spacing:
.05pt'>Page Fault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体;letter-spacing:.05pt'>异常处理实现</span></p>
<p class=MsoListParagraph align=left style='margin-left:41.15pt;text-align:
left;text-indent:-18.0pt;text-autospace:none'><span style='font-size:12.0pt;
letter-spacing:.05pt'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体;
letter-spacing:.05pt'>了解页替换算法在操作系统中的实现</span></p>
<p class=MsoNormal align=left style='margin-left:23.15pt;text-align:left;
text-autospace:none'><span style='font-size:12.0pt;letter-spacing:.05pt'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.7pt;text-align:left;
text-autospace:none'><b><span style='font-size:17.0pt'>2    </span></b><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体;letter-spacing:.05pt'>实验内</span><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体'></span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>做完实验二后,大家可以了解并掌握物理内存管理中的连续空间分配算法的具体实现以及如何建立二级页表。本次实验是在实验二的基础上,借助于页表机制和实验一中涉及的中断异常处理机制,完成</span><span
style='font-size:12.0pt'>Page Fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>异常处理和</span><span style='font-size:12.0pt'>FIFO</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>页替换算法的实现,结合磁盘提供的缓存空间,从而能够支持虚存管理,提供一个比实际物理内存空间</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>更大</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的虚拟内存空间给系统使用。实际操作系统系统中的虚拟内存管理设计与实现是相当复杂的,涉及到与进程管理系统、文件系统等的交叉访问。如果大家有余力,可以尝试完成扩展练习,实现</span><span
style='font-size:12.0pt'>extended  clock</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>页替换算法。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>2.1 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>练习</span></b></p>
<p class=MsoNormal style='margin-right:34.95pt;text-autospace:none'><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:red'>练习</span></b><b><span
style='font-size:12.0pt;color:red'>0 </span></b><b><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:red'>:填写已有实验</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>本实验依赖实验</span><span
style='font-size:12.0pt'>1/2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>。请把你做的实验</span><span style='font-size:12.0pt'>1/2</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的代码填入本实验中代码中有</span><span
style='font-size:12.0pt'>“LAB1”,“LAB2”</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的注释相应部分。</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-autospace:none'><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:red'>练习</span></b><b><span
style='font-size:12.0pt;color:red'>1</span></b><b><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:red'>:给未被映射的地址映射上物理页(需要编程)</span></b></p>
<p class=MsoNormalIndent style='text-indent:24.0pt'><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>完成</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>mm/vmm.c</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>)函数,给未被映射的地址映射上物理页。设置访问权限</span><span lang=ZH-CN
style='font-size:12.0pt'> </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的时候需要参考页面所在</span><span style='font-size:12.0pt'> VMA </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的权限,同时需要注意映射物理页时需要操作内存控制</span><span
lang=ZH-CN style='font-size:12.0pt'> </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>结构所指定的页表,而不是内核的页表。注意:在</span><span style='font-size:
12.0pt'>LAB2 EXERCISE 1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>处填写代码。执行</span><span style='font-size:12.0pt'>“make qemu”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>后,如果通过</span><span
style='font-size:12.0pt'>check_pgfault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>函数的测试后,会有</span><span style='font-size:12.0pt'>“check_pgfault()
succeeded!”</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的输出,表示练习</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>基本正确。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-autospace:none'><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:red'>练习</span></b><b><span
style='font-size:12.0pt;color:red'>2</span></b><b><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:red'>:补充完成基于</span></b><b><span
style='font-size:12.0pt;color:red'>FIFO</span></b><b><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:red'>的页面替换算法(需要编程)</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>完成</span><span style='font-size:12.0pt'>vmm.c</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的</span><span
style='font-size:12.0pt'>do_pgfault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>函数,并且在实现</span><span style='font-size:12.0pt'>FIFO</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>算法的</span><span
style='font-size:12.0pt'>swap_fifo.c</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>中完成</span><span style='font-size:12.0pt'>map_swappable</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>swap_out_vistim</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>函数。通过对</span><span style='font-size:
12.0pt'>swap</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的测试。注意:在</span><span
style='font-size:12.0pt'>LAB2 EXERCISE 2</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>处填写代码。执行</span><span style='font-size:
12.0pt'>“make qemu”</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>后,如果通过</span><span style='font-size:12.0pt'>check_swap</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数的测试后,会有</span><span
style='font-size:12.0pt'>“check_swap() succeeded!”</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>的输出,表示练习</span><span style='font-size:
12.0pt'>2</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>基本正确。</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-autospace:none'><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:red'>扩展练习</span></b><b><span
style='font-size:12.0pt;color:red'>Challenge</span></b><b><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:red'>:实现识别</span></b><b><span
style='font-size:12.0pt;color:red'>dirty bit</span></b><b><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:red'></span></b><b><span
style='font-size:12.0pt;color:red'>extended clock</span></b><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:red'>页替换算法(需要编程)</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.1pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;color:black;
letter-spacing:.05pt'>challenge</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体;color:black;letter-spacing:.05pt'>部分不是必做部分,不过在正确最后会酌情加分</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:black'><span
style='letter-spacing:-.05pt'>需写出有详细</span><span style='letter-spacing:.05pt'>设计、分析和测试的实验报告。完成出色的可获得适当加分</span><span
style='letter-spacing:-6.95pt'></span><span style='letter-spacing:.05pt'></span>基本实验完成后一<span
style='letter-spacing:.05pt'>周内完成,单独提交</span>)。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>    </span></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>2.2 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>项目组成</span></b></p>
<p class=MsoNormal align=center style='margin-left:5.65pt;text-align:center;
text-autospace:none'><b><span lang=ZH-CN style='font-size:14.0pt;font-family:
楷体'></span></b><b><span style='font-size:14.0pt'>1</span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'></span></b><b><span
lang=ZH-CN style='font-size:14.0pt'> </span></b><b><span lang=ZH-CN
style='font-size:14.0pt;font-family:楷体'>实验三文件列表</span></b></p>
<div align=center>
<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='margin-left:33.75pt;border-collapse:collapse;border:none'>
<tr>
<td width=397 valign=top style='width:14.0cm;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormalIndent style='text-indent:7.3pt'><span style='font-size:
9.0pt'>     |-- boot</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|-- kern</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |-- driver</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |<span style='color:black'>-- …</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:red'>ide.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   `--<span style='color:red'> ide.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |-- <span style='color:red'>fs</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt;color:black'>|   |   |-- </span><span style='font-size:9.0pt;
color:red'>fs.h</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt;color:black'>|   |   |-- </span><span style='font-size:9.0pt;
color:red'>swapfs.c</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   `-- <span style='color:red'>swapfs.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |-- init</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt;color:black'>|   |   |-- …</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   `-- <span style='color:#7030A0'>init.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |-- mm</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:#7030A0'>default_pmm.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:#7030A0'>default_pmm.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |--<span style='color:#7030A0'> memlayout.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- mmu.h</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:#7030A0'>pmm.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:#7030A0'>pmm.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><a name="OLE_LINK3"><a
name="OLE_LINK2"><span style='font-size:9.0pt'>|   |   |-- <span
style='color:red'>swap.c</span></span></a></a></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:red'>swap.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:red'>swap_fifo.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:red'>swap_fifo.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   |-- <span style='color:red'>vmm.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |   `-- <span style='color:red'>vmm.h</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   |-- sync</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|   `-- trap</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|       |-- <span style='color:#7030A0'>trap.c</span></span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|       `-- …</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|-- libs</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|       |-- list.h</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>|       `-- …</span></p>
<p class=MsoNormalIndent style='text-indent:18.0pt'><span style='font-size:
9.0pt'>`-- tools</span></p>
</td>
</tr>
</table>
</div>
<p class=MsoNormalIndent style='text-indent:21.0pt'><span>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.75pt;line-height:17.9pt;text-autospace:
none'><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>相对与实验二,实验三主要增加的文件如上表红色部分所示,主要修改的文件如上表紫色部分所示,其他需要用到的重要文件用黑色表示。主要改动如下:</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/mm/default_pmm.[ch]</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>:实现基于</span><span style='font-size:
12.0pt'>struct</span><span style='font-size:12.0pt'>&nbsp;</span><span
style='font-size:12.0pt'>pmm_manager</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>类框架的</span><span style='font-size:12.0pt'>Fist-Fit</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>物理内存分配参考实现(分配最小单位为页,即</span><span
style='font-size:12.0pt'>4096</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>字节),相关分配页和释放页等实现会间接被</span><span style='font-size:12.0pt'>kmalloc/kfree</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>等函数使用。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/mm/pmm.[ch]</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>pmm.h</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>定义物理内存分配类框架</span><span
style='font-size:12.0pt'>struct</span><span style='font-size:12.0pt'>&nbsp;</span><span
style='font-size:12.0pt'>pmm_manager</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>&nbsp;</span><span
style='font-size:12.0pt'>pmm.c</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>包含了对此物理内存分配类框架的访问,以及与建立、修改、访问页表相关的各种函数实现。在本实验中会用到</span><span
style='font-size:12.0pt'>kmalloc/kfree</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>等函数。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>libs/list.h</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>:定义了通用双向链表结构以及相关的查找、插入等基本操作,这是建立基于链表方法的物理内存管理(以及其他内核功能)的基础。在</span><span
style='font-size:12.0pt'>lab0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>文档中有相关描述。其他有类似双向链表需求的内核功能模块可直接使用</span><span style='font-size:
12.0pt'>list.h</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中定义的函数。在本实验中会多次用到插入,删除等操作函数。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/driver/ide.[ch]</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>:定义和实现了内存页</span><span
style='font-size:12.0pt'>swap</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>机制所需的磁盘扇区的读写操作支持;在本实验中会涉及通过</span><span style='font-size:12.0pt'>swapfs_*</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数间接使用文件中的函数。故了解即可。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/fs/*</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>:定义和实现了内存页</span><span style='font-size:12.0pt'>swap</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>机制所需从磁盘读数据到内存页和写内存数据到磁盘上去的函数</span><span
style='font-size:12.0pt'> swapfs_read/swapfs_write</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>。在本实验中会涉及使用这两个函数。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/mm/memlayout.h</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>:修改了</span><span style='font-size:12.0pt'>struct
Page</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,增加了两项</span><span
style='font-size:12.0pt'>pra_*</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>成员结构,其中</span><span style='font-size:12.0pt'>pra_page_link</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>可以用来建立描述各个页访问情况(比如根据访问先后)的链表。在本实验中会涉及使用这两个成员结构,以及</span><span
style='font-size:12.0pt'>le2page</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>等宏。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/mm/vmm.[ch]</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>vmm.h</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>描述了</span><span
style='font-size:12.0pt'>mm_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>等表述可访问的虚存地址访问的一些信息,下面会进一步详细讲解。</span><span
style='font-size:12.0pt'>vmm.c</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>涉及</span><span style='font-size:12.0pt'>mm,vma</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>结构数据的创建</span><span
style='font-size:12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>销毁</span><span style='font-size:12.0pt'>/</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>查找</span><span
style='font-size:12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>插入等函数,这些函数在</span><span style='font-size:12.0pt'>check_vma</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>check_vmm</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>等中被使用,理解即可。而</span><span style='font-size:12.0pt'>page
fault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>处理相关的</span><span
style='font-size:12.0pt'>do_pgfault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>函数是本次实验需要涉及完成的。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/mm/swap.[ch]</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>:定义了实现<a name="OLE_LINK4">页替换算法的</a>类框架</span><span
style='font-size:12.0pt'>struct swap_manager</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>swap.c</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>包含了对此页替换算法类框架的初始化、页换入</span><span
style='font-size:12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>换出等各种函数实现。重点是要理解何时调用</span><span style='font-size:12.0pt'>swap_out</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>swap_in</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>函数。和如何在此框架下连接具体的页替换算法实现。</span><span style='font-size:12.0pt'>check_swap</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数以及被此函数调用的</span><span
style='font-size:12.0pt'>_fifo_check_swap</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>函数完成了对本次实验中的练习</span><span
style='font-size:12.0pt'>2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>FIFO</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>页替换算法基本正确性的检查,可了解,便于知道为何产生错误。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt'>kern/mm/swap_fifo.[ch]</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'></span><span style='font-size:12.0pt;
letter-spacing:.05pt'>FIFO</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体;letter-spacing:.05pt'>页替换算法的</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>基于类框架</span><span style='font-size:
12.0pt'>struct swap_manager</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'><span style='letter-spacing:.05pt'>简化实现,主要被</span></span><span
style='font-size:12.0pt;letter-spacing:.05pt'>swap.c</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>的相关函数调用。重点是</span><span
style='font-size:12.0pt;letter-spacing:.05pt'>_fifo_map_swappable</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>函数(可用于建立页访问属性和关系,比如访问时间的先后顺序)和</span><span
style='font-size:12.0pt;letter-spacing:.05pt'>_fifo_swap_out_victim</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>函数(可用于实现挑选出要换出的页),当然换出哪个页需要借助于</span><span
style='font-size:12.0pt;letter-spacing:.05pt'>fifo_map_swappable</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>函数建立的某种属性关系,已选出合适的页。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.75pt;margin-bottom:
0cm;margin-left:23.7pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'><span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
style='font-size:12.0pt;letter-spacing:.05pt'>kern/mm/mmu.h</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>:其中定义额也页表项的各种属性位,比如</span><span
style='font-size:12.0pt;letter-spacing:.05pt'>PTE_P\PET_D\PET_A</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>等,对于实现扩展实验的</span><span
style='font-size:12.0pt;letter-spacing:.05pt'>clock</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>算法会有帮助。</span></p>
<p class=MsoNormal style='margin-right:9.75pt;line-height:17.9pt;text-autospace:
none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.75pt;line-height:17.9pt;text-autospace:
none'><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>本次实验的主要练习集中在</span><span
style='font-size:12.0pt'>vmm.c</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中的</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数和</span><span
style='font-size:12.0pt'>swap_fifo.c</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>中的</span><span style='font-size:12.0pt;letter-spacing:
.05pt'>_fifo_map_swappable</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体;letter-spacing:.05pt'>函数、</span><span style='font-size:12.0pt;
letter-spacing:.05pt'>_fifo_swap_out_victim</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;letter-spacing:.05pt'>函数。</span></p>
<p class=MsoNormal style='margin-right:9.75pt;line-height:17.9pt;text-autospace:
none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-autospace:none'><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>编译执行</span></b></p>
<p class=MsoNormal align=left style='margin-top:.7pt;text-align:left;
line-height:10.0pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>编译并运行代码的命令如下:</span></p>
<p class=MsoBodyText style='margin-left:21.0pt'><span>make</span></p>
<p class=MsoBodyText style='margin-left:21.0pt'><span>make qemu</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>则可以得到如附录所示的显示内容(仅供参考,不是标准答案输出)</span></p>
<p class=MsoNormal align=left style='margin-top:.65pt;text-align:left;
line-height:10.0pt;text-autospace:none'><span style='font-size:10.0pt;
color:black'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.7pt;text-align:left;
text-autospace:none'><b><span style='font-size:17.0pt'>3 </span></b><b><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体'>虚拟内存管理</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span style='font-size:14.0pt'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>3.1 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>基本原理概述</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>什么是虚拟内存?简单地说,是指程序员或</span><span style='font-size:12.0pt'>CPU “</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>需要</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>和直接</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>看到</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的内存,这其实暗示了两点:</span><span style='font-size:12.0pt'>1</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>、虚拟内存单元不一定有实际的物理内存单元对应,即实际的物理内存单元可能不存在;</span><span
style='font-size:12.0pt'>2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>、如果虚拟内存单元对应有实际的物理内存单元,那二者的地址一般不是相等的。通过操作系统的某种内存管理和映射技术可建立虚拟内存与实际的物理内存的对应关系,使得程序员或</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>访问的虚拟内存地址会转换为另外一个物理内存地址。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>那么这个</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>虚拟</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的作用或意义在哪里体现呢?在操作系统中,虚拟内存其实包含多个虚拟层次,在不同的层次体现了不同的作用。首先,在有了分页机制后,程序员或</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>直接</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>看到</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的地址已经不是实际的物理地址了,这已经有一层虚拟化,我们可简称为内存地址虚拟化。有了内存地址虚拟化,我们就可以通过设置页表项来限定软件运行时的访问空间,确保软件运行不越界,完成内存访问保护的功能。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>通过内存地址虚拟化,可以使得软件在没有访问某虚拟内存地址时不分配具体的物理内存,而只有在实际访问某虚拟内存地址时,操作系统再动态地分配物理内存,建立虚拟内存到物理内存的页映射关系,这种技术属于</span><span
style='font-size:12.0pt'>lazy load</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>技术,简称按需分页(</span><span style='font-size:12.0pt'>demand
paging</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>)。把不经常访问的数据所占的内存空间临时写到硬盘上,这样可以腾出更多的空闲内存空间给经常访问的数据;当</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>访问到不经常访问的数据时,再把这些数据从硬盘读入到内存中,这种技术称为页换入换出(</span><span
style='font-size:12.0pt'>page swap in/out</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>)。这种内存管理技术给了程序员更大的内存</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>空间</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,我们称为内存空间虚拟化。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><b><span style='font-size:14.0pt'>&nbsp;</span></b></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>3.2 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>实验执行流程概述</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>本次实验主要完成</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>内核对虚拟内存的管理工作。其总体设计思路还是比较简单,即首先完成初始化虚拟内存管理机制,即需要设置好哪些页需要放在物理内存中,哪些页不需要放在物理内存中,而是可被换出到硬盘上,并涉及完善建立页表映射、页错误异常处理操作等函数实现。然后就执行一组访存测试,看看我们建立的页表项是否能够正确完成虚实地址映射,是否正确描述了虚拟内存页在物理内存中还是在硬盘上,是否能够正确把虚拟内存页在物理内存和硬盘之间进行传递,是否正确实现了页面替换算法等。</span><span
style='font-size:12.0pt'>lab3</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的总体执行流程如下。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>首先是初始化过程。参考</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>总控函数</span><span
style='font-size:12.0pt'>init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的代码,可以看到在调用完成虚拟内存初始化的</span><span style='font-size:12.0pt'>vmm_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数之前,需要首先调用</span><span
style='font-size:12.0pt'>pmm_init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>函数完成物理内存的管理,这也是我们</span><span style='font-size:12.0pt'>lab2</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>已经完成的内容。接着是执行中断和异常相关的初始化工作,即调用</span><span
style='font-size:12.0pt'>pic_init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>函数和</span><span style='font-size:12.0pt'>idt_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数等,这些工作与</span><span
style='font-size:12.0pt'>lab1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的中断异常初始化工作的内容是相同的。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>在调用完</span><span style='font-size:12.0pt'>idt_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数之后,将进一步调用三个</span><span
style='font-size:12.0pt'>lab3</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中才有的新函数</span><span style='font-size:12.0pt'>vmm_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>ide_init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>swap_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>。这三个函数设计了本次实验中的两个练习。第一个函数</span><span
style='font-size:12.0pt'>vmm_init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>是检查我们的练习</span><span style='font-size:12.0pt'>1</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>是否正确实现了。为了表述不在物理内存中的“合法”虚拟页,需要有数据结构来描述这样的页,为此</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>建立了</span><span style='font-size:12.0pt'>mm_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>vma_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>数据结构(在</span><span style='font-size:12.0pt'>3.3</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>小节中有进一步详细描述),假定我们已经描述好了这样的“合法”虚拟页,当</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>访问这些“合法”虚拟页时,会由于没有虚实地址映射而产生页错误异常。如果我们正确实现了练习</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,则</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数会申请一个空闲物理页,并建立好虚实映射关系,从而使得这样的“合法”虚拟页有实际的物理页帧对应。这样练习</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>就算完成了。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>ide_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>swap_init</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>是为练习</span><span style='font-size:12.0pt'>2</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>准备的。由于页面置换算法的实现存在对硬盘数据块的读写,所以</span><span
style='font-size:12.0pt'>ide_init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>就是完成对用于页换入换出的硬盘(简称</span><span style='font-size:12.0pt'>swap</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>硬盘)的初始化工作。完成</span><span
style='font-size:12.0pt'>ide_init</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>函数后,</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>就可以对这个</span><span
style='font-size:12.0pt'>swap</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>硬盘进行读写操作了。</span><span style='font-size:12.0pt'>swap_init</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数首先建立</span><span
style='font-size:12.0pt'>swap_manager</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>swap_manager</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>是完成页面替换过程的主要功能模块,其中包含了页面置换算法的实现(具体内容可参考</span><span
style='font-size:12.0pt'>5</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>小节)。然后会进一步调用执行</span><span style='font-size:12.0pt'>check_swap</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数在内核中分配一些页,模拟对这些页的访问,这会产生页错误异常。如果我们正确实现了练习</span><span
style='font-size:12.0pt'>2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,就可通过</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>来调用</span><span
style='font-size:12.0pt'>swap_map_swappable</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>函数来查询这些页的访问情况并间接调用实现页面置换算法的相关函数,把</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>不常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的页换出到磁盘上。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>在实现上述技术时,需要解决三个关键问题:</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:63.7pt;margin-bottom:.0001pt;text-indent:-14.05pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>1、<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>当程序运行中访问内存产生</span><span
style='font-size:12.0pt'>page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>异常时,如何判定这个引起异常的虚拟地址内存访问是越界、写只读页的</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>非法地址</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>访问还是由于数据被临时换出到磁盘上或还没有分配内存的</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>合法地址</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>访问?</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:63.7pt;margin-bottom:.0001pt;text-indent:-14.05pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>2、<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>何时进行请求调页</span><span style='font-size:
12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>页换入换出处理?</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:63.7pt;margin-bottom:.0001pt;text-indent:-14.05pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>3、<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>如何在现有</span><span style='font-size:
12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的基础上实现页替换算法?</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>接下来将进一步分析完成</span><span style='font-size:12.0pt'>lab3</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>主要注意的关键问题和涉及的关键数据结构。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>3.3 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>关键数据结构和相关函数分析</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>对于第一个问题的出现,在于实验二中有关内存的数据结构和相关操作都是直接针对实际存在的资源</span><span
style='font-size:12.0pt'>--</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>物理内存空间的管理,没有从一般应用程序对内存的</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>需求</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>考虑,即需要有相关的数据结构和操作来体现一般应用程序对虚拟内存的</span><span style='font-size:
12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>需求</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>。一般应用程序的对虚拟内存的</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>需求</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>与物理内存空间的</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>供给</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>没有直接的对应关系,</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>是通过</span><span
style='font-size:12.0pt'>page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>异常处理来间接完成这二者之间的衔接。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>page_fault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数不知道哪些是“合法”的虚拟页,原因是</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>还缺少一定的数据结构来描述这种不在物理内存中的“合法”虚拟页。为此</span><span style='font-size:
12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>通过建立</span><span
style='font-size:12.0pt'>mm_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>数据结构,描述了</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>模拟应用程序运行所需的合法内存空间。当访问内存产生</span><span style='font-size:12.0pt'>page
fault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>异常时,可获得访问的内存的方式(读或写)以及具体的虚拟内存地址,这样</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>就可以查询此地址,看是否属于</span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>数据结构中描述的合法地址范围中,如果在,则可根据具体情况进行请求调页</span><span
style='font-size:12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>页换入换出处理(这就是练习</span><span style='font-size:12.0pt'>2</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>涉及的部分);如果不在,则报错。</span><span
style='font-size:12.0pt'>mm_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>数据结构结合页</span><img
width=520 height=528 src="lab3.files/image001.png" align=left hspace=9><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>表表示虚拟地址空间和物理地址空间的示意图如下所示:</span></p>
<p class=MsoNormal align=center style='margin-right:9.8pt;text-align:center;
text-indent:24.0pt;line-height:17.9pt;text-autospace:none'><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'> 
</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>虚拟地址空间和物理地址空间的示意图</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中描述应用程序对虚拟内存</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>需求</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的数据结构是</span><span
style='font-size:12.0pt'>vma_struct </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>(定义在</span><span style='font-size:12.0pt'>vmm.h</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中),以及针对</span><span
style='font-size:12.0pt'>vma_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的函数操作。这里把一个</span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>结构的变量简称为</span><span
style='font-size:12.0pt'>vma</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>变量。</span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的定义如下:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:23.7pt;border-collapse:collapse;border:none'>
<tr>
<td width=463 valign=top style='width:463.3pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span>struct vma_struct {</span></p>
<p class=MsoNormal><span>      // the set of vma using the same PDT </span></p>
<p class=MsoNormal style='text-indent:26.25pt'><span>struct mm_struct *vm_mm;
</span></p>
<p class=MsoNormal><span>          uintptr_t vm_start;                          //
start addr of vma         </span></p>
<p class=MsoNormal><span>          uintptr_t vm_end;                           //
end addr of vma</span></p>
<p class=MsoNormal style='text-indent:26.25pt'><span>uint32_t vm_flags;      
                  // flags of vma</span></p>
<p class=MsoNormal style='text-indent:15.75pt'><span>//linear list link which
sorted by start addr of vma</span></p>
<p class=MsoNormal style='text-indent:26.25pt'><span>list_entry_t list_link; 
</span></p>
<p class=MsoNormal><span>};</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>vm_start</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>vm_end</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>描述了一个连续地址的虚拟内存空间的起始位置和结束位置,这两个值都应该是</span><span
style='font-size:12.0pt'> PGSIZE </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>对齐的,而且描述的是一个合理的地址空间范围(即严格确保</span><span style='font-size:12.0pt'>
vm_start &lt; vm_end </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的关系);</span><span style='font-size:12.0pt'>list_link</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>是一个双向链表,按照从小到大的顺序把一系列用</span><span
style='font-size:12.0pt'>vma_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>表示的虚拟内存空间链接起来,并且还要求这些链起来的</span><span style='font-size:
12.0pt'> vma_struct </span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>应该是不相交的,即</span><span style='font-size:12.0pt'>vma</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>之间的地址空间无交集;</span><span
style='font-size:12.0pt'>vm_flags</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>表示了这个虚拟内存空间的属性,目前的属性包括:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:23.7pt;border-collapse:collapse;border:none'>
<tr>
<td width=463 valign=top style='width:463.3pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span>#define VM_READ          0x00000001 //</span><span
style='font-family:楷体'>只读</span></p>
<p class=MsoNormal><span>#define VM_WRITE        0x00000002 //</span><span
style='font-family:楷体'>可读写</span></p>
<p class=MsoNormal><span>#define VM_EXEC          0x00000004 //</span><span
style='font-family:楷体'>可执行</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>vm_mm</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>是一个指针,指向一个比</span><span
style='font-size:12.0pt'>vma_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>更高的抽象层次的数据结构</span><span style='font-size:12.0pt'>mm_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,这里把一个</span><span
style='font-size:12.0pt'>mm_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>结构的变量简称为</span><span style='font-size:12.0pt'>mm</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>变量。这个数据结构表示了包含所有虚拟内存空间的共同属性,具体定义如下</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:23.7pt;border-collapse:collapse;border:none'>
<tr>
<td width=463 valign=top style='width:463.3pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span>struct mm_struct {</span></p>
<p class=MsoNormal><span>     // linear list link which sorted by start addr
of vma</span></p>
<p class=MsoNormal><span>            list_entry_t mmap_list; </span></p>
<p class=MsoNormal style='text-indent:31.5pt'><span>// current accessed vma,
used for speed purpose</span></p>
<p class=MsoNormal><span>            struct vma_struct *mmap_cache; </span></p>
<p class=MsoNormal><span>            pde_t *pgdir;  // the PDT of these vma</span></p>
<p class=MsoNormal><span>            int map_count; // the count of these vma</span></p>
<p class=MsoNormal><span>            void *sm_priv;   // the private data for
swap manager</span></p>
<p class=MsoNormal><span>};</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>mmap_list</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>是双向链表头,链接了所有属于同一页目录表的虚拟内存空间,</span><span
style='font-size:12.0pt'>mmap_cache</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>是指向当前正在使用的虚拟内存空间,由于操作系统执行的</span><span style='font-size:
12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>局部性</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>原理,当前正在用到的虚拟内存空间在接下来的操作中可能还会用到,这时就不需要查链表,而是直接使用此指针就可找到下一次要用到的虚拟内存空间。由于</span><span
style='font-size:12.0pt'> mmap_cache </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的引入,可使得</span><span style='font-size:12.0pt'> mm_struct </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>数据结构的查询加速</span><span
style='font-size:12.0pt'> 30% </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>以上。</span><span style='font-size:12.0pt'>pgdir </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>所指向的就是</span><span
style='font-size:12.0pt'> mm_struct </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>数据结构所维护的页表。通过访问</span><span style='font-size:12.0pt'>pgdir</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>可以查找某虚拟地址对应的页表项是否存在以及页表项的属性等。</span><span
style='font-size:12.0pt'>map_count</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>记录</span><span style='font-size:12.0pt'> mmap_list </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>里面链接的</span><span
style='font-size:12.0pt'> vma_struct </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的个数。</span><span style='font-size:12.0pt'>sm_priv</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>指向用来链接记录页访问情况的链表头,这建立了</span><span
style='font-size:12.0pt'>mm_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>和后续要讲到的</span><span style='font-size:12.0pt'>swap_manager</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>之间的联系。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>涉及</span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的操作函数也比较简单,主要包括三个:</span></p>
<p class=MsoNormal style='margin-left:39.3pt;text-indent:-21.0pt'><span
style='font-size:12.0pt;font-family:Wingdings'>l<span style='font:7.0pt "Times New Roman"'>&nbsp;
</span></span><span style='font-size:12.0pt'>vma_create--</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>创建</span><span
style='font-size:12.0pt'>vma</span></p>
<p class=MsoNormal style='margin-left:39.3pt;text-indent:-21.0pt'><span
style='font-size:12.0pt;font-family:Wingdings'>l<span style='font:7.0pt "Times New Roman"'>&nbsp;
</span></span><span style='font-size:12.0pt'>insert_vma_struct--</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>插入一个</span><span
style='font-size:12.0pt'>vma</span></p>
<p class=MsoNormal style='margin-left:39.3pt;text-indent:-21.0pt'><span
style='font-size:12.0pt;font-family:Wingdings'>l<span style='font:7.0pt "Times New Roman"'>&nbsp;
</span></span><span style='font-size:12.0pt'>find_vma--</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>查询</span><span style='font-size:12.0pt'>vma</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>vma_create</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数根据输入参数</span><span
style='font-size:12.0pt'>vm_start</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>vm_end</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>vm_flags</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>来创建并初始化描述一个虚拟内存空间的</span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>结构变量。</span><span
style='font-size:12.0pt'>insert_vma_struct</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>函数完成把一个</span><span style='font-size:
12.0pt'>vma</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>变量按照其空间位置</span><span
style='font-size:12.0pt'>[vma-&gt;vm_start,vma-&gt;vm_end]</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>从小到大的顺序插入到所属的</span><span
style='font-size:12.0pt'>mm</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>变量中的</span><span style='font-size:12.0pt'>mmap_list</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>双向链表中。</span><span
style='font-size:12.0pt'>find_vma</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>根据输入参数</span><span style='font-size:12.0pt'>addr</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>mm</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>变量,查找在</span><span style='font-size:12.0pt'>mm</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>变量中的</span><span
style='font-size:12.0pt'>mmap_list</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>双向链表中某个</span><span style='font-size:12.0pt'>vma</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>包含此</span><span
style='font-size:12.0pt'>addr</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,即</span><span style='font-size:12.0pt'>vma-&gt;vm_start&lt;=
addr &lt;vma-&gt;end</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>。这三个函数与后续讲到的</span><span style='font-size:12.0pt'>page fault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>异常处理有紧密联系。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>涉及</span><span style='font-size:12.0pt'>mm_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的操作函数比较简单,只有</span><span
style='font-size:12.0pt'>mm_create</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>mm_destroy</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>两个函数,从字面意思就可以看出是是完成</span><span
style='font-size:12.0pt'>mm_struct</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>结构的变量创建和删除。在</span><span style='font-size:12.0pt'>mm_create</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中用</span><span
style='font-size:12.0pt'>kmalloc</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>分配了一块空间,所以在</span><span style='font-size:12.0pt'>mm_destroy</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中也要对应进行释放。在</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>运行过程中,会产生描述虚拟内存空间的</span><span style='font-size:12.0pt'>vma_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>结构,所以在</span><span
style='font-size:12.0pt'>mm_destroy</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>中也要进对这些</span><span style='font-size:12.0pt'>mmap_list</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的</span><span
style='font-size:12.0pt'>vma</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>进行释放。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.7pt;text-align:left;
text-autospace:none'><b><span style='font-size:17.0pt'>4  Page Fault</span></b><b><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体'>异常处理</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>对于第三节提到的第二个关键问题,解决的关键是</span><span style='font-size:12.0pt'>page
fault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>异常处理过程中主要涉及的函数</span><span
style='font-size:12.0pt'> -- do_pgfault</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>。在程序的执行过程中由于某种原因(页框不存在</span><span
style='font-size:12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>写只读页等)而使</span><span style='font-size:12.0pt'> CPU </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>无法最终访问到相应的物理内存单元,即无法完成从虚拟地址到物理地址映射时,</span><span
style='font-size:12.0pt'>CPU </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>会产生一次页错误异常,从而需要进行相应的页错误异常服务例程。这个页错误异常处理的时机就是求调页</span><span
style='font-size:12.0pt'>/</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>页换入换出</span><span style='font-size:12.0pt'>/</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>处理的执行时机。当相关处理完成后,页错误异常服务例程会返回到产生异常的指令处重新执行,使得软件可以继续正常运行下去。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>具体而言,当启动分页机制以后,如果一条指令或数据的虚拟地址所对应的物理页框不在内存中或者访问的类型有错误(比如写一个只读页或用户态程序访问内核态的数据等),就会发生页错误异常。产生页面异常的原因主要有:</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:42.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>目标页面不存在(页表项全为</span><span
style='font-size:12.0pt'>0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,即该线性地址与物理地址尚未建立映射或者已经撤销</span><span style='font-size:12.0pt'>)</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:42.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>相应的物理页面不在内存中(页表项非空,但</span><span
style='font-size:12.0pt'>Present</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>标志位</span><span style='font-size:12.0pt'>=0</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,比如在</span><span
style='font-size:12.0pt'>swap</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>分区或磁盘文件上</span><span style='font-size:12.0pt'>)</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,这将在下面介绍换页机制实现时进一步讲解如何处理;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:42.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>访问权限不符合</span><span style='font-size:
12.0pt'>(</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>此时页表项</span><span
style='font-size:12.0pt'>P</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>标志</span><span style='font-size:12.0pt'>=1</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,比如企图写只读页面</span><span
style='font-size:12.0pt'>).</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>当出现上面情况之一,那么就会产生页面</span><span style='font-size:12.0pt'>page
fault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>#PF</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>)异常。产生异常的线性地址存储在</span><span style='font-size:12.0pt'>CR2</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中,并且将是</span><span
style='font-size:12.0pt'>page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的产生类型保存在</span><span style='font-size:12.0pt'> error
code </span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中,比如</span><span
style='font-size:12.0pt'> bit 0 </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>表示是否</span><span style='font-size:12.0pt'> PTE_P</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>bit 1 </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>表示是否</span><span
style='font-size:12.0pt'> write </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>操作。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>产生页错误异常后,</span><span style='font-size:12.0pt'>CPU</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>硬件和软件都会做一些事情来应对此事。首先页错误异常也是一种异常,所以针对一般异常的硬件处理操作是必须要做的,即</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>在当前内核栈保存当前被打断的程序现场,即依次压入当前被打断程序使用的</span><span
style='font-size:12.0pt'>eflags</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>cs</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>eip</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>errorCode</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>;由于页错误异常的中断号是</span><span
style='font-size:12.0pt'>0xE</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>&nbsp;</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>把异常中断号</span><span style='font-size:12.0pt'>0xE</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>对应的中断异常服务例程的地址(</span><span
style='font-size:12.0pt'>vectors.S</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>中的标号</span><span style='font-size:12.0pt'>vector14</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>处)加载到</span><span
style='font-size:12.0pt'>cs</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>eip</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>寄存器中,开始执行中断服务例程。这时</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>开始处理异常中断,首先需要保存硬件没有保存的寄存器。在</span><span style='font-size:12.0pt'>vectors.S</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的标号</span><span
style='font-size:12.0pt'>vector14</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>处先把中断号压入内核栈,然后再在</span><span style='font-size:12.0pt'>trapentry.S</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的标号</span><span
style='font-size:12.0pt'>__alltraps</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>处把</span><span style='font-size:12.0pt'>ds</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>es</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>和其他通用寄存器都压栈。自此,被打断的程序现场被保存在内核栈中。接下来,在</span><span
style='font-size:12.0pt'>trap.c</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>trap</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数开始了中断服务例程的处理流程,大致调用关系为:</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>trap--&gt;
trap_dispatch--&gt;pgfault_handler--&gt;do_pgfault</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>下面需要具体分析一下</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数。</span><span
style='font-size:12.0pt'>do_pgfault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的调用关系如下图所示:</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><img width=507 height=312
src="lab3.files/image002.png" align=left hspace=9></p>
<p class=MsoNormal align=center style='margin-right:9.8pt;text-align:center;
text-indent:24.0pt;line-height:17.9pt;text-autospace:none'><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>
do_pgfault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的调用关系图</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>产生页错误异常后,</span><span style='font-size:12.0pt'>CPU</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>把引起页错误异常的虚拟地址装到寄存器</span><span
style='font-size:12.0pt'>CR2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中,并给出了出错码(</span><span style='font-size:12.0pt'>tf-&gt;tf_err</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>),指示引起页错误异常的存储器访问的类型。而中断服务例程会调用页错误异常处理函数</span><span
style='font-size:12.0pt'>do_pgfault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>进行具体处理。页错误异常处理是实现按需分页、</span><span style='font-size:
12.0pt'>swap in/out</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>的关键之处。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>do_pgfault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>函数是完成页错误异常处理的主要函数,它根据从</span><span style='font-size:
12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的控制寄存器</span><span
style='font-size:12.0pt'>CR2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中获取的页错误异常的虚拟地址以及根据</span><span style='font-size:12.0pt'> error
code</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的错误类型来查找此虚拟地址是否在某个</span><span
style='font-size:12.0pt'>VMA</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的地址范围内以及是否满足正确的读写权限,如果在此范围内并且权限也正确,这认为这是一次合法访问,但没有建立虚实对应关系。所以需要分配一个空闲的内存页,并修改页表完成虚地址到物理地址的映射,刷新</span><span
style='font-size:12.0pt'>TLB</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,然后调用</span><span style='font-size:12.0pt'>iret</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中断,返回到产生页错误异常的指令处重新执行此指令。如果该虚地址不再某</span><span
style='font-size:12.0pt'>VMA</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>范围内,这认为是一次非法访问。</span></p>
<p class=MsoNormal align=left style='margin-top:.65pt;text-align:left;
line-height:10.0pt;text-autospace:none'><span style='font-size:10.0pt;
color:black'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.7pt;text-align:left;
text-autospace:none'><b><span style='font-size:17.0pt'>5  </span></b><b><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体'>页面置换机制的实现</span></b><b><span
lang=ZH-CN style='font-size:17.0pt'> </span></b></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>5.1 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>页替换算法</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>操作系统为何要进行页面置换呢?这是由于操作系统给用户态的应用程序提供了一个虚拟的</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>大容量</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>内存空间,而实际的物理内存空间又没有那么大。所以操作系统就就</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>瞒着</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>应用程序,只把应用程序中</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的数据和代码放在物理内存中,而不常用的数据和代码放在了硬盘这样的存储介质上。如果应用程序访问的是</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的数据和代码,那么操作系统已经放置在内存中了,不会出现什么问题。但当应用程序访问它认为应该在内存中的的数据或代码时,如果这些数据或代码不在内存中,则根据上一小节的介绍,会产生页错误异常。这时,操作系统必须能够应对这种页错误异常,即尽快把应用程序当前需要的数据或代码放到内存中来,然后重新执行应用程序产生异常的访存指令。如果在把硬盘中对应的数据或代码调入内存前,操作系统发现物理内存已经没有空闲空间了,这时操作系统必须把它认为</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>不常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的页换出到磁盘上去,以腾出内存空闲空间给应用程序所需的数据或代码。</span><span
lang=ZH-CN style='font-size:12.0pt'> </span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>操作系统迟早会碰到没有内存空闲空间而必须要置换出内存中某个</span><span style='font-size:
12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>不常用</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页的情况。如何判断内存中哪些是</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>常用</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页,哪些是</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>不常用</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页,把</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>常用</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页保持在内存中,在物理内存空闲空间不够的情况下,把</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>不常用</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页置换到硬盘上就是页替换算法着重考虑的问题。容易理解,一个好的页替换算法会导致页错误异常次数少,也就意味着访问硬盘的次数也少,从而使得应用程序执行的效率就高。本次实验涉及的页替换算法(包括扩展练习):</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>先进先出</span><span style='font-size:12.0pt'>(First
In First Out, FIFO)</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>页替换算法:该算法总是淘汰最先进入内存的页,即选择在内存中驻留时间最久的页予以淘汰。只需把一个应用程序在执行过程中已调入内存的页按先后次序链接成一个队列,队列头指向内存中驻留时间最久的页,队列尾指向最近被调入内存的页。这样需要淘汰页时,从队列头很容易查找到需要淘汰的页。</span><span
style='font-size:12.0pt'>FIFO</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>算法只是在应用程序按线性顺序访问地址空间时效果才好,否则效率不高。因为那些常被访问的页,往往在内存中也停留得最久,结果它们因变</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>而不得不被置换出去。</span><span
style='font-size:12.0pt'>FIFO</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>算法的另一个缺点是,它有一种异常现象(</span><span style='font-size:12.0pt'>Belady</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>现象),即在增加放置页的页帧的情况下,反而使页错误异常次数增多。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>时钟(</span><span style='font-size:12.0pt'>Clock</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>)页替换算法:也称最近未使用</span><span
style='font-size:12.0pt'> (Not Used Recently, NUR) </span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>页替换算法。虽然二次机会算法是一个较合理的算法,但它经常需要在链表中移动页面,这样做既降低了效率,又是不必要的。一个更好的办法是把各个页面组织成环形链表的形式,类似于一个钟的表面。然后把一个指针指向最古老的那个页面,或者说,最先进来的那个页面。时钟算法和第二次机会算法的功能是完全一样的,只是在具体实现上有所不同。时钟算法需要在页表项(</span><span
style='font-size:12.0pt'>PTE</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>)中设置了一位访问位来表示此页表项对应的页当前是否被访问过。当该页被访问时,</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中的</span><span style='font-size:12.0pt'>MMU</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>硬件将把访问位置</span><span
style='font-size:12.0pt'>“1”</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>。然后将内存中所有的页都通过指针链接起来并形成一个循环队列。初始时,设置一个当前指针指向某页(比如最古老的那个页面)。操作系统需要淘汰页时,对当前指针指向的页所对应的页表项进行查询,如果访问位为</span><span
style='font-size:12.0pt'>“0”</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,则淘汰该页,把它换出到硬盘上;如果访问位为</span><span style='font-size:12.0pt'>“1”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,这将该页表项的此位置</span><span
style='font-size:12.0pt'>“0”</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,继续访问下一个页。该算法近似地体现了</span><span style='font-size:12.0pt'>LRU</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的思想,且易于实现,开销少。但该算法需要硬件支持来设置访问位,且该算法在本质上与</span><span
style='font-size:12.0pt'>FIFO</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>算法是类似的,惟一不同的是在</span><span style='font-size:12.0pt'>clock</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>算法中跳过了访问位为</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>改进的时钟(</span><span style='font-size:
12.0pt'>Enhanced Clock</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>)页替换算法:在时钟置换算法中,淘汰一个页面时只考虑了页面是否被访问过,但在实际情况中,还应考虑被淘汰的页面是否被修改过。因为淘汰修改过的页面还需要写回硬盘,使得其置换代价大于未修改过的页面。改进的时钟置换算法除了考虑页面的访问情况,还需考虑页面的修改情况。即该算法不但希望淘汰的页面是最近未使用的页,而且还希望被淘汰的页是在主存驻留期间其页面内容未被修改过的。这需要为每一页的对应页表项内容中增加一位引用位和一位修改位。当该页被访问时,</span><span
style='font-size:12.0pt'>CPU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中的</span><span style='font-size:12.0pt'>MMU</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>硬件将把访问位置</span><span
style='font-size:12.0pt'>“1”</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>。当该页被</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>时,</span><span style='font-size:12.0pt'>CPU</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的</span><span
style='font-size:12.0pt'>MMU</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>硬件将把修改位置</span><span style='font-size:12.0pt'>“1”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>。这样这两位就存在四种可能的组合情况:(</span><span
style='font-size:12.0pt'>0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>0</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>)表示最近未被引用也未被修改,首先选择此页淘汰;(</span><span
style='font-size:12.0pt'>0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>1</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>)最近未被使用,但被修改,其次选择;(</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>0</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>)最近使用而未修改,再次选择;(</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>1</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>)最近使用且修改,最后选择。该算法与时钟算法相比,可进一步减少磁盘的</span><span
style='font-size:12.0pt'>I/O</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>操作次数,但为了查找到一个尽可能适合淘汰的页面,可能需要经过多次扫描,增加了算法本身的执行开销。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><b><span style='font-size:12.0pt;color:black'>&nbsp;</span></b></p>
<p class=MsoNormal align=left style='margin-left:5.65pt;text-align:left;
text-autospace:none'><b><span style='font-size:14.0pt'>5.2 </span></b><b><span
lang=ZH-CN style='font-size:14.0pt;font-family:楷体'>页面置换机制</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>如果要实现页面置换机制,只考虑页替换算法的设计与实现是远远不够的,还需考虑其他问题:</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>哪些页可以被换出?</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>一个虚拟的页如何与硬盘上的扇区建立对应关系?</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>何时进行换入和换出操作?</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>如何设计数据结构已支持页替换算法?</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt;font-family:Wingdings'>l<span
style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>如何完成页的换入换出操作?</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>这些问题在下面会逐一进行分析。注意,在实验三中仅实现了简单的页面置换机制,但现在还没有涉及实验四和实验五才实现的内核线程和用户进程,所以还无法通过内核线程机制实现一个完整意义上的虚拟内存页面置换功能。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:34.95pt;
margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;
text-autospace:none'><span style='font-size:12.0pt'>1.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><b><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>可以被换出的页</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>在操作系统的设计中,一个基本的原则是:并非所有的物理页都可以交换出去的,只有映射到用户空间且被用户程序直接访问的页面才能被交换,而被内核直接使用的内核空间的页面不能被换出。这里面的原因是什么呢?操作系统是执行的关键代码,需要保证运行的高效性和实时性,如果在操作系统执行过程中,发生了缺页现象,则操作系统不得不等很长时间(硬盘的访问速度比内存的访问速度慢</span><span
style='font-size:12.0pt'>2~3</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>个数量级),这将导致整个系统运行低效。而且,不难想象,处理缺页过程所用到的内核代码或者数据如果被换出,整个内核都面临崩溃的危险。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>但在实验三实现的</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中,我们只是实现了换入换出机制,还没有设计用户态执行的程序,所以我们在实验三中仅仅通过执行</span><span
style='font-size:12.0pt'>check_swap</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>函数在内核中分配一些页,模拟对这些页的访问,然后通过</span><span style='font-size:
12.0pt'>do_pgfault</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>来调用</span><span style='font-size:12.0pt'>swap_map_swappable</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数来查询这些页的访问情况并间接调用相关函数,换出</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>不常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的页到磁盘上。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:34.95pt;
margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;
text-autospace:none'><span style='font-size:12.0pt'>2.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><b><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>虚存中的页与硬盘上的扇区之间的映射关系</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>如果一个页被置换到了硬盘上,那操作系统如何能简捷来表示这种情况呢?在</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的设计上,充分利用了页表中的</span><span style='font-size:12.0pt'>PTE</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>来表示这种情况:当一个</span><span
style='font-size:12.0pt'> PTE </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>用来描述一般意义上的物理页时,显然它应该维护各种权限和映射关系,以及应该有</span><span
style='font-size:12.0pt'> PTE_P </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>标记;但当它用来描述一个被置换出去的物理页时,它被用来维护该物理页与</span><span
style='font-size:12.0pt'> swap </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>磁盘上扇区的映射关系,并且该</span><span style='font-size:12.0pt'> PTE </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>不应该由</span><span
style='font-size:12.0pt'> MMU </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>将它解释成物理页映射</span><span style='font-size:12.0pt'>(</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>即没有</span><span
style='font-size:12.0pt'> PTE_P </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>标记</span><span style='font-size:12.0pt'>)</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,与此同时对应的权限则交由</span><span
style='font-size:12.0pt'> mm_struct </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>来维护,当对位于该页的内存地址进行访问的时候,必然导致</span><span
style='font-size:12.0pt'> page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>,然后</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>能够根据</span><span
style='font-size:12.0pt'> PTE </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>描述的</span><span style='font-size:12.0pt'> swap </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>项将相应的物理页重新建立起来,并根据虚存所描述的权限重新设置好</span><span
style='font-size:12.0pt'> PTE </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>使得内存访问能够继续正常进行。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>如果一个页(</span><span style='font-size:12.0pt'>4KB/</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>页)被置换到了硬盘某</span><span
style='font-size:12.0pt'>8</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>个扇区(</span><span style='font-size:12.0pt'>0.5KB/</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>扇区),该</span><span
lang=ZH-CN style='font-size:12.0pt'> </span><span style='font-size:12.0pt'>PTE</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的最低位</span><span
style='font-size:12.0pt'>--present</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>位应该为</span><span style='font-size:12.0pt'>0 </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>(即</span><span
style='font-size:12.0pt'> PTE_P </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>标记为空,表示虚实地址映射关系不存在),接下来的</span><span style='font-size:12.0pt'>7</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>位暂时保留,可以用作各种扩展;而原来用来表示页帧号的高</span><span
style='font-size:12.0pt'>24</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>位地址,恰好可以用来表示此页在硬盘上的起始扇区的位置(其从第几个扇区开始)。为了在页表项中区别</span><span
style='font-size:12.0pt'> 0 </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'> swap </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>分区的映射,将</span><span
style='font-size:12.0pt'> swap </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>分区的一个</span><span style='font-size:12.0pt'> page </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>空出来不用,也就是说一个高</span><span
style='font-size:12.0pt'>24</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>位不为</span><span style='font-size:12.0pt'>0</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,而最低位为</span><span
style='font-size:12.0pt'>0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>PTE</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>表示了一个放在硬盘上的页的起始扇区号(见</span><span
style='font-size:12.0pt'>swap.h</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>中对</span><span style='font-size:12.0pt'>swap_entry_t</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的描述):</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:26.7pt;border-collapse:collapse;border:none'>
<tr>
<td width=418 valign=top style='width:418.15pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span>swap_entry_t</span></p>
<p class=MsoNormal><span>  --------------------------------------------</span></p>
<p class=MsoNormal><span>  |         offset        |   reserved   | 0  |</span></p>
<p class=MsoNormal><span>  --------------------------------------------</span></p>
<p class=MsoNormal><span>            24 bits            7 bits    1 bit</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>考虑到硬盘的最小访问单位是一个扇区,而一个扇区的大小为</span><span style='font-size:12.0pt'>512</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>2^8</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>)字节,所以需要</span><span style='font-size:12.0pt'>8</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>个连续扇区才能放置一个</span><span
style='font-size:12.0pt'>4KB</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的页。在</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中,用了第二个</span><span
style='font-size:12.0pt'>IDE</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>硬盘来保存被换出的扇区,根据实验三的输出信息</span></p>
<p class=MsoNormal style='text-indent:12.0pt'><span style='font-size:12.0pt'>“ide
1:     262144(sectors), 'QEMU HARDDISK'.”</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>我们可以知道实验三可以保存</span><span style='font-size:12.0pt'>262144/8=32768</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>个页,即</span><span
style='font-size:12.0pt'>128MB</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的内存空间。</span><span style='font-size:12.0pt'>swap </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>分区的大小是</span><span
style='font-size:12.0pt'> swapfs_init </span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>里面根据磁盘驱动的接口计算出来的,目前</span><span style='font-size:12.0pt'>
ucore </span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>里面要求</span><span
style='font-size:12.0pt'> swap </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>磁盘至少包含</span><span style='font-size:12.0pt'> 1000 </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'> page</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,并且至多能使用</span><span style='font-size:12.0pt'> 1&lt;&lt;24 </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>page</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:34.95pt;
margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;
text-autospace:none'><span style='font-size:12.0pt'>3.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><b><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>执行换入换出的时机</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>在实验三中,</span><span style='font-size:12.0pt'> check_mm_struct</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>变量这个数据结构表示了目前</span><span
style='font-size:12.0pt'> ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>认为合法的所有虚拟内存空间集合,而</span><span style='font-size:12.0pt'>mm</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的每个</span><span
style='font-size:12.0pt'>vma</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>表示了一段地址连续的合法虚拟空间。当</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>或应用程序访问地址所在的页不在内存时,就会产生</span><span
style='font-size:12.0pt'> page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>异常,引起调用</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数,此函数会判断产生访问异常的地址属于</span><span
style='font-size:12.0pt'>check_mm_struct</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>某个</span><span style='font-size:12.0pt'>vma</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>表示的合法虚拟地址空间,且保存在硬盘</span><span
style='font-size:12.0pt'>swap</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>文件中(即对应的</span><span style='font-size:12.0pt'>PTE</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的高</span><span
style='font-size:12.0pt'>24</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>位不为</span><span style='font-size:12.0pt'>0</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,而最低位为</span><span
style='font-size:12.0pt'>0</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>),则是执行页换入的时机,将调用</span><span style='font-size:12.0pt'>swap_in</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数完成页面换入。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>换出页面的时机相对复杂一些,针对不同的策略有不同的时机。</span><span style='font-size:12.0pt'>ucore</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>目前大致有两种策略,即积极换出策略和消极换出策略。积极换出策略是指操作系统周期性地(或在系统不忙的时候)主动把某些认为</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>不常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的页换出到硬盘上,从而确保系统中总有一定数量的空闲页存在,这样当需要空闲页时,基本上能够及时满足需求;消极换出策略是指,只是当试图得到空闲页时,发现当前没有空闲的物理页可供分配,这时才开始查找</span><span
style='font-size:12.0pt'></span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>不常用</span><span style='font-size:12.0pt'></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>页面,并把一个或多个这样的页换出到硬盘上。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>在实验三中的基本练习中,支持上述第二种情况。对于第一种积极换出策略,即每隔</span><span
style='font-size:12.0pt'>1</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>秒执行一次的实现积极的换出策略,可考虑在扩展练习中实现。对于第二种消极的换出策略,则是在</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>调用</span><span style='font-size:12.0pt'>alloc_pages</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数获取空闲页时,此函数如果发现无法从物理内存页分配器(比如</span><span
style='font-size:12.0pt'>first fit</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>)获得空闲页,就会进一步调用</span><span style='font-size:12.0pt'>swap_out</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数换出某页,实现一种消极的换出策略。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:34.95pt;
margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;
text-autospace:none'><span style='font-size:12.0pt'>4.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><b><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>页替换算法的数据结构设计</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>到实验二为止,我们知道目前表示内存中物理页使用情况的变量是基于数据结构</span><span
style='font-size:12.0pt'>Page</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的全局变量</span><span style='font-size:12.0pt'>pages</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>数组,</span><span
style='font-size:12.0pt'>pages</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>的每一项表示了计算机系统中一个物理页的使用情况。为了表示物理页可被换出或已被换出的情况,可对</span><span
style='font-size:12.0pt'>Page</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>数据结构进行扩展:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:19.6pt;border-collapse:collapse;border:none'>
<tr>
<td width=467 valign=top style='width:467.4pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span>struct Page {</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span>……</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span>list_entry_t       </span>&nbsp;<span>pra_page_link;</span>&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p class=MsoNormal style='text-indent:21.0pt'><span>uintptr_t</span>&nbsp;<span>          
pra_vaddr;</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span>};</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-indent:24.0pt'><span style='font-size:12.0pt'>pra_page_link</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>可用来构造按页的第一次访问时间进行排序的一个链表,这个链表的开始表示第一次访问时间最近的页,链表结尾表示第一次访问时间最远的页。当然链表头可以就可设置为</span><span
style='font-size:12.0pt'>pra_list_head</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>(定义在</span><span style='font-size:12.0pt'>swap_fifo.c</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中),构造的时机实在</span><span
style='font-size:12.0pt'>page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>发生后,进行</span><span style='font-size:12.0pt'>do_pgfault</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数时。</span><span
style='font-size:12.0pt'>pra_vaddr</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>可以用来记录此物理页对应的虚拟页起始地址。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>当一个物理页</span><span lang=ZH-CN style='font-size:12.0pt'> </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>struct Page</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span lang=ZH-CN style='font-size:12.0pt'> </span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>需要被</span><span
style='font-size:12.0pt'> swap </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>出去的时候,首先需要确保它已经分配了一个位于磁盘上的</span><span style='font-size:12.0pt'>swap
page</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>(由连续的</span><span
style='font-size:12.0pt'>8</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>个扇区组成)。这里为了简化设计,在</span><span style='font-size:12.0pt'>swap_check</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数中建立了每个虚拟页唯一对应的</span><span
style='font-size:12.0pt'>swap page</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>,其对应关系设定为:虚拟页对应的</span><span style='font-size:12.0pt'>PTE</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的索引值</span><span
style='font-size:12.0pt'> = swap page</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的扇区起始位置</span><span style='font-size:12.0pt'>*8</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>为了实现各种页替换算法,我们设计了一个页替换算法的类框架</span><span style='font-size:12.0pt'>swap_manager:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=512 valign=top style='width:511.8pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span>struct</span><span>&nbsp;</span><span>swap_manager<br>
{<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>const</span><span>&nbsp;</span><span>char</span><span>&nbsp;</span><span>*name;<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>Global</span><span>&nbsp;</span><span>initialization</span><span>&nbsp;</span><span>for</span><span>&nbsp;</span><span>the</span><span>&nbsp;</span><span>swap</span><span>&nbsp;</span><span>manager</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*init)</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>(void);<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>Initialize</span><span>&nbsp;</span><span>the</span><span>&nbsp;</span><span>priv</span><span>&nbsp;</span><span>data</span><span>&nbsp;</span><span>inside</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*init_mm)</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>(struct</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*mm);<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>Called</span><span>&nbsp;</span><span>when</span><span>&nbsp;</span><span>tick</span><span>&nbsp;</span><span>interrupt</span><span>&nbsp;</span><span>occured</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*tick_event)</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>(struct</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*mm);<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>Called</span><span>&nbsp;</span><span>when</span><span>&nbsp;</span><span>map</span><span>&nbsp;</span><span>a</span><span>&nbsp;</span><span>swappable</span><span>&nbsp;</span><span>page</span><span>&nbsp;</span><span>into</span><span>&nbsp;</span><span>the</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*map_swappable)</span><span>&nbsp;&nbsp;&nbsp;</span><span>(struct</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*mm,</span><span>&nbsp;</span><span>uintptr_t</span><span>&nbsp;</span><span>addr,</span><span>&nbsp;</span><span>struct</span><span>&nbsp;</span><span>Page</span><span>&nbsp;</span><span>*page,</span><span>&nbsp;</span><span>int</span><span>&nbsp;</span><span>swap_in);<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>When</span><span>&nbsp;</span><span>a</span><span>&nbsp;</span><span>page</span><span>&nbsp;</span><span>is</span><span>&nbsp;</span><span>marked</span><span>&nbsp;</span><span>as</span><span>&nbsp;</span><span>shared,</span><span>&nbsp;</span><span>this</span><span>&nbsp;</span><span>routine</span><span>&nbsp;</span><span>is</span><span>&nbsp;</span><span>called</span><span>&nbsp;</span><span>to</span><span>&nbsp;</span><span>delete</span><span>&nbsp;</span><span>the</span><span>&nbsp;</span><span>addr</span><span>&nbsp;</span><span>entry</span><span>&nbsp;</span><span>from</span><span>&nbsp;</span><span>the</span><span>&nbsp;</span><span>swap</span><span>&nbsp;</span><span>manager</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*set_unswappable)</span><span>&nbsp;</span><span>(struct</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*mm,</span><span>&nbsp;</span><span>uintptr_t</span><span>&nbsp;</span><span>addr);<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>Try</span><span>&nbsp;</span><span>to</span><span>&nbsp;</span><span>swap</span><span>&nbsp;</span><span>out</span><span>&nbsp;</span><span>a</span><span>&nbsp;</span><span>page,</span><span>&nbsp;</span><span>return</span><span>&nbsp;</span><span>then</span><span>&nbsp;</span><span>victim</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*swap_out_victim)</span><span>&nbsp;</span><span>(struct</span><span>&nbsp;</span><span>mm_struct</span><span>&nbsp;</span><span>*mm,</span><span>&nbsp;</span><span>struct</span><span>&nbsp;</span><span>Page</span><span>&nbsp;</span><span>**ptr_page,</span><span>&nbsp;</span><span>int</span><span>&nbsp;</span><span>in_tick);<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*</span><span>&nbsp;</span><span>check</span><span>&nbsp;</span><span>the</span><span>&nbsp;</span><span>page</span><span>&nbsp;</span><span>relpacement</span><span>&nbsp;</span><span>algorithm</span><span>&nbsp;</span><span>*/<br>
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span><span>&nbsp;</span><span>(*check_swap)(void);</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span><br>
};</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>这里关键的两个函数指针是</span><span style='font-size:12.0pt'>map_swappable</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>swap_out_vistim</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>,前一个函数用于记录页访问情况相关属性,后一个函数用于挑选需要换出的页。显然第二个函数依赖与第一个函数记录的页访问情况。</span><span
style='font-size:12.0pt'>tick_event</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>函数指针也很重要,结合定时产生的中断,可以实现一种积极的换页策略。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:34.95pt;
margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-indent:-18.0pt;
text-autospace:none'><span style='font-size:12.0pt'>5.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><b><span style='font-size:12.0pt'>swap_check</span></b><b><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的检查实现</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>下面具体讲述一下实验三中实现置换算法的页面置换的检查执行逻辑,便于大家实现练习</span><span
style='font-size:12.0pt'>2</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>。实验三页面置换的检查过程在函数</span><span style='font-size:12.0pt'>swap_check
</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>kern/mm/swap.c</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>中)中,其大致流程如下。</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>1.<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>调用</span><span
style='font-size:12.0pt'>mm_create</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>建立</span><span style='font-size:12.0pt'>mm</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>变量,并调用</span><span
style='font-size:12.0pt'>vma_create</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>创建</span><span style='font-size:12.0pt'>vma</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>变量,设置合法的访问范围为</span><span
style='font-size:12.0pt'>4KB~24KB</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>2.<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>调用</span><span
style='font-size:12.0pt'>free_page</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>等操作,模拟形成一个只有</span><span style='font-size:12.0pt'>4</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>个空闲</span><span
style='font-size:12.0pt'> physical page</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>;并设置了从</span><span style='font-size:
12.0pt'>4KB~24KB</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>的连续</span><span style='font-size:12.0pt'>5</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>个虚拟页的访问操作;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>3.<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>设置记录缺页次数的变量</span><span
style='font-size:12.0pt'>pgfault_num=0</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>,执行</span><span style='font-size:12.0pt'>check_content_set</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>函数,使得起始地址分别对起始地址为</span><span
style='font-size:12.0pt'>0x1000, 0x2000, 0x3000, 0x4000</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>的虚拟页按时间顺序先后写操作访问,由于之前没有建立页表,所以会产生</span><span
style='font-size:12.0pt'>page fault</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>异常,如果完成练习</span><span style='font-size:12.0pt'>1</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>,则这些从</span><span
style='font-size:12.0pt'>4KB~20KB</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'></span><span style='font-size:12.0pt'>4</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>虚拟页会与</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>保存的</span><span style='font-size:12.0pt'>4</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>个物理页帧建立映射关系;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>4.<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>然后对虚页对应的新产生的页表项进行合法性检查;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>5.<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>然后进入测试页替换算法的主体,执行函数</span><span
style='font-size:12.0pt'>check_content_access</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>,并进一步调用到</span><span style='font-size:
12.0pt'>_fifo_check_swap</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>函数,如果通过了所有的</span><span style='font-size:12.0pt'>assert</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>。这进一步表示</span><span
style='font-size:12.0pt'>FIFO</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>页替换算法基本正确实现;</span></p>
<p class=MsoListParagraph style='margin-top:0cm;margin-right:9.8pt;margin-bottom:
0cm;margin-left:45.0pt;margin-bottom:.0001pt;text-indent:-21.0pt;line-height:
17.9pt;text-autospace:none'><span style='font-size:12.0pt'>6.<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>最后恢复</span><span
style='font-size:12.0pt'>ucore</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>环境。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span style='font-size:12.0pt;color:black'>&nbsp;</span></p>
<p class=MsoNormal align=left style='margin-left:5.7pt;text-align:left;
text-autospace:none'><b><span style='font-size:17.0pt'>6  </span></b><b><span
lang=ZH-CN style='font-size:17.0pt;font-family:楷体'>实验报告要求</span></b></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>从网站上下载</span><span style='font-size:12.0pt'>lab3.zip</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>后,解压得到本文档和代码目录</span><span
style='font-size:12.0pt'> lab3</span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>,完成实验中的各个练习。完成代码编写并检查无误后,在对应目录下执行</span><span style='font-size:
12.0pt'> make handin </span><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体'>任务,即会自动生成</span><span style='font-size:12.0pt'>
lab3-handin.tar.gz</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>。最后请一定提前或按时提交到网络学堂上。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-indent:24.0pt;line-height:
17.9pt;text-autospace:none'><span lang=ZH-CN style='font-size:12.0pt;
font-family:楷体;color:black'>注意有</span><span style='font-size:12.0pt;color:black'>“LAB3”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:black'>的注释,代码中所有需要完成的地方</span><span
lang=ZH-CN style='font-family:楷体'></span><span>challenge</span><span
lang=ZH-CN style='font-family:楷体'>除外)</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体;color:black'>都有</span><span style='font-size:12.0pt;
color:black'>“LAB3”</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体;color:black'></span><span style='font-size:12.0pt;color:black'>“YOUR CODE”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体;color:black'>的注释,请在提交时特别注意保持注释,并将</span><span
style='font-size:12.0pt;color:black'>“YOUR CODE”</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:black'>替换为自己的学号,并且将所有标有对应注释的部分填上正确的代码。所有扩展实验的加分总和不超过</span><span
style='font-size:12.0pt;color:black'>10</span><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体;color:black'>分。</span></p>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>附录:正确输出的参考:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=512 valign=top style='width:511.8pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>yuchen@yuchen-PAI4:~/oscourse/2012spring/lab3/lab3-code-2012$
make qemu</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>(THU.CST) os is loading ...</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>Special kernel symbols:</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  entry  0xc010002c (phys)</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  etext  0xc010962b (phys)</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  edata  0xc0122ac8 (phys)</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  end    0xc0123c10 (phys)</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>Kernel executable memory footprint: 143KB</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>memory management: default_pmm_manager</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>e820map:</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  memory: 0009f400, [00000000, 0009f3ff], type = 1.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  memory: 00000c00, [0009f400, 0009ffff], type = 2.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  memory: 00010000, [000f0000, 000fffff], type = 2.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  memory: 07efd000, [00100000, 07ffcfff], type = 1.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  memory: 00003000, [07ffd000, 07ffffff], type = 2.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  memory: 00040000, [fffc0000, ffffffff], type = 2.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_alloc_page() succeeded!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_pgdir() succeeded!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_boot_pgdir() succeeded!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>-------------------- BEGIN --------------------</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>PDE(0e0) c0000000-f8000000 38000000 urw</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  |-- PTE(38000) c0000000-f8000000 38000000 -rw</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>PDE(001) fac00000-fb000000 00400000 -rw</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  |-- PTE(000e0) faf00000-fafe0000 000e0000 urw</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>  |-- PTE(00001) fafeb000-fafec000 00001000 -rw</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>--------------------- END ---------------------</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_vma_struct() succeeded!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00000100: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_pgfault() succeeded!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_vmm() succeeded.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>ide 0:      10000(sectors), 'QEMU HARDDISK'.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>ide 1:     262144(sectors), 'QEMU HARDDISK'.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>SWAP: manager = fifo swap manager</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>BEGIN check_swap: count 1, total 31992</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'> mm-&gt;sm_priv c0123c04 in fifo_init_mm</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>setup Page Table for vaddr 0X1000, so alloc a page</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>setup Page Table vaddr 0~4MB OVER!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>set up init env for check_swap begin!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00001000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00002000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00003000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00004000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>set up init env for check_swap over!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page c in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page a in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page d in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page b in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page e in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00005000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_out: i 0, store page in vaddr 0x1000 to disk
swap entry 2</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page b in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page a in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00001000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_out: i 0, store page in vaddr 0x2000 to disk
swap entry 3</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_in: load disk swap entry 2 with swap_page in vadr
0x1000</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page b in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00002000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_out: i 0, store page in vaddr 0x3000 to disk
swap entry 4</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_in: load disk swap entry 3 with swap_page in
vadr 0x2000</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page c in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00003000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_out: i 0, store page in vaddr 0x4000 to disk
swap entry 5</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_in: load disk swap entry 4 with swap_page in
vadr 0x3000</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>write Virt Page d in fifo_check_swap</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>page fault at 0x00004000: K/W [no page found].</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_out: i 0, store page in vaddr 0x5000 to disk
swap entry 6</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>swap_in: load disk swap entry 5 with swap_page in
vadr 0x4000</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>check_swap() succeeded!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>++ setup timer interrupts</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>100 ticks</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>End of Test.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>kernel panic at kern/trap/trap.c:20:</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>    EOT: kernel seems ok.</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>Welcome to the kernel debug monitor!!</span></p>
<p class=MsoNormal style='margin-right:9.8pt;text-autospace:none'><span
style='font-size:7.5pt'>Type 'help' for a list of commands.</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='margin-right:9.8pt;line-height:17.9pt;text-autospace:
none'><span style='font-size:13.0pt;color:red'>&nbsp;</span></p>
</div>
</body>
</html>