ucore_os_docs/lab7.htm

1877 lines
122 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 http-equiv=Content-Type content="text/html; charset=utf-8">
<meta name=Generator content="Microsoft Word 14 (filtered)">
<style>
<!--
/* Font Definitions */
@font-face
{font-family:Arial;
panose-1:2 11 6 4 2 2 2 2 2 4;}
@font-face
{font-family:"Courier New";
panose-1:2 7 3 9 2 2 5 2 4 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:Cambria;
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
{font-family:"Lucida Sans";
panose-1:2 11 6 2 3 5 4 2 2 4;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 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:OpenSymbol;}
@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;}
@font-face
{font-family:SIL-Hei-Med-Jian;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman";}
h1
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:21.6pt;
text-indent:-21.6pt;
font-size:16.0pt;
font-family:Arial;
font-weight:bold;}
h2
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:12.0pt;
margin-left:28.8pt;
text-indent:-28.8pt;
line-height:150%;
font-size:14.0pt;
font-family:Arial;
font-weight:bold;}
h3
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:36.0pt;
text-indent:-36.0pt;
font-size:10.0pt;
font-family:Arial;
font-weight:bold;}
h4
{margin-top:14.0pt;
margin-right:0cm;
margin-bottom:14.5pt;
margin-left:0cm;
line-height:156%;
font-size:14.0pt;
font-family:Cambria;
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.MsoList, li.MsoList, div.MsoList
{margin-top:0cm;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:0cm;
font-size:12.0pt;
font-family:"Times New Roman";}
a:link, span.MsoHyperlink
{color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{color:purple;
text-decoration:underline;}
p.MsoDocumentMap, li.MsoDocumentMap, div.MsoDocumentMap
{margin:0cm;
margin-bottom:.0001pt;
font-size:9.0pt;
font-family:;}
p
{margin-right:0cm;
margin-left:0cm;
font-size:12.0pt;
font-family:;}
code
{font-family:;}
pre
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
{margin:0cm;
margin-bottom:.0001pt;
font-size:9.0pt;
font-family:"Times New Roman";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{margin:0cm;
margin-bottom:.0001pt;
text-indent:21.0pt;
font-size:12.0pt;
font-family:"Times New Roman";}
p.Heading, li.Heading, div.Heading
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:0cm;
font-size:14.0pt;
font-family:Arial;}
span.Bullets
{font-family:OpenSymbol;}
p.15, li.15, div.15
{margin:0cm;
margin-bottom:.0001pt;
text-indent:10.0pt;
line-height:150%;
font-size:12.0pt;
font-family:"Times New Roman";}
p.1, li.1, div.1
{margin-top:6.0pt;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:0cm;
font-size:10.0pt;
font-family:"Times New Roman";
font-style:italic;}
p.Index, li.Index, div.Index
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman";}
p.a, li.a, div.a
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:0cm;
margin-left:28.9pt;
margin-bottom:.0001pt;
text-indent:-28.9pt;
font-size:14.0pt;
font-family:;
font-weight:bold;
font-style:italic;}
p.2, li.2, div.2
{margin-top:12.0pt;
margin-right:5.0pt;
margin-bottom:12.0pt;
margin-left:5.0pt;
text-indent:-28.8pt;
line-height:150%;
font-size:14.0pt;
font-family:;
font-weight:bold;}
p.150, li.150, div.150
{margin:0cm;
margin-bottom:.0001pt;
text-indent:10.0pt;
line-height:150%;
font-size:12.0pt;
font-family:;}
p.3, li.3, div.3
{margin-top:12.0pt;
margin-right:0cm;
margin-bottom:12.0pt;
margin-left:36.0pt;
text-indent:-36.0pt;
line-height:150%;
font-size:10.0pt;
font-family:;}
span.WW8Num7z1
{font-family:"Courier New";}
span.HTML
{font-family:;}
.MsoChpDefault
{font-size:10.0pt;}
/* Page Definitions */
@page WordSection1
{size:595.25pt 841.85pt;
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 link=blue vlink=purple>
<div class=WordSection1>
<h1 align=center style='margin-left:0cm;text-align:center;text-indent:0cm;
page-break-before:always'><span lang=ZH-CN style='font-family:楷体'>实验七:同步互斥</span></h1>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:14.0pt;
font-family:楷体;letter-spacing:.05pt'>1. <span lang=ZH-CN>实验目的</span></span></b></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>熟悉</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>中的进程同步机制,了解操作系统为进程同步提供的底层支持;</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'></span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>中理解信号量(</span><span>semaphore</span><span
lang=ZH-CN style='font-family:楷体'>)机制的具体实现;</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>理解管程机制,在</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>内核中增加基于管程(</span><span>monitor</span><span
lang=ZH-CN style='font-family:楷体'>)的条件变量(</span><span>condition variable</span><span
lang=ZH-CN style='font-family:楷体'>)的支持;</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>了解经典进程同步问题,并能使用同步机制解决进程同步问题。</span></p>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:14.0pt;
font-family:楷体;letter-spacing:.05pt'>2 <span lang=ZH-CN>实验内容</span></span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>实验六完成了用户进程的调度框架和具体的调度算法,可调度运行多个进程。如果多个进程需要协同操作或访问共享资源,则存在如何同步和有序竞争的问题。本次实验,主要是熟悉</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>的进程同步机制</span><span></span><span lang=ZH-CN
style='font-family:楷体'>信号量(</span><span>semaphore</span><span lang=ZH-CN
style='font-family:楷体'>)机制,以及基于信号量的哲学家就餐问题解决方案。然后掌握管程的概念和原理,并参考信号量机制,实现基于管程的条件变量机制和基于条件变量来解决哲学家就餐问题。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>在本次实验中,在</span><span>kern/sync/check_sync.c</span><span lang=ZH-CN
style='font-family:楷体'>中提供了一个基于信号量的哲学家就餐问题解法。同时还需完成练习,即实现基于管程(主要是灵活运用条件变量和互斥信号量)的哲学家就餐问题解法。哲学家就餐问题描述如下:有五个哲学家,他们的生活方式是交替地进行思考和进餐。哲学家们公用一张圆桌,周围放有五把椅子,每人坐一把。在圆桌上有五个碗和五根筷子,当一个哲学家思考时,他不与其他人交谈,饥饿时便试图取用其左、右最靠近他的筷子,但他可能一根都拿不到。只有在他拿到两根筷子时,方能进餐,进餐完后,放下筷子又继续思考。</span></p>
<p class=MsoNormal style='margin-left:6.5pt;text-autospace:none'><b><span
style='font-size:16.0pt'>2.1 </span></b><b><span lang=ZH-CN style='font-size:
16.0pt;font-family:楷体'>练习</span></b></p>
<p class=MsoNormal style='margin-right:34.95pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><b><span lang=ZH-CN style='font-family:
楷体;color:red'>练习</span></b><b><span style='color:red'>0</span></b><b><span
lang=ZH-CN style='font-family:楷体;color:red'>:填写已有实验</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>本实验依赖实验</span><span>1/2/3/4/5/6</span><span
lang=ZH-CN style='font-family:楷体'>。请把你做的实验</span><span>1/2/3/4/5/6</span><span
lang=ZH-CN style='font-family:楷体'>的代码填入本实验中代码中有</span><span>“LAB1”/“LAB2”/“LAB3”/“LAB4”/“LAB5”/“LAB6”</span><span
lang=ZH-CN style='font-family:楷体'>的注释相应部分。并确保编译通过。注意:为了能够正确执行</span><span>lab7</span><span
lang=ZH-CN style='font-family:楷体'>的测试应用程序,可能需对已完成的实验</span><span>1/2/3/4/5/6</span><span
lang=ZH-CN style='font-family:楷体'>的代码进行进一步改进。</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><b><span lang=ZH-CN style='font-family:
楷体;color:red'>练习</span></b><b><span style='color:red'>1 </span></b><b><span
lang=ZH-CN style='font-family:楷体;color:red'>理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码)</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>完成练习</span><span>0</span><span
lang=ZH-CN style='font-family:楷体'>后,建议大家比较一下(可用</span><span>kdiff3</span><span
lang=ZH-CN style='font-family:楷体'>等文件比较软件)个人完成的</span><span>lab6</span><span
lang=ZH-CN style='font-family:楷体'>和练习</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>完成后的刚修改的</span><span>lab7</span><span lang=ZH-CN
style='font-family:楷体'>之间的区别,分析了解</span><span>lab7</span><span lang=ZH-CN
style='font-family:楷体'>采用信号量的执行过程。执行</span><span>make grade</span><span
lang=ZH-CN style='font-family:楷体'>,大部分测试用例应该通过。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><b><span lang=ZH-CN style='font-family:
楷体;color:red'>练习</span></b><b><span style='color:red'>2 </span></b><b><span
lang=ZH-CN style='font-family:楷体;color:red'>完成内核级条件变量和基于内核级条件变量的哲学家就餐问题(需要编码)</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>首先掌握管程机制,然后基于信号量实现完成条件变量实现,然后用管程机制实现<span>哲学家就餐问题的解决方案(基于条件变量)。</span></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>执行:</span><span>make
grade </span><span lang=ZH-CN style='font-family:楷体'>。如果所显示的应用程序检测都输出</span><span>ok</span><span
lang=ZH-CN style='font-family:楷体'>,则基本正确。如果只是某程序过不去,比如</span><span>matrix.c</span><span
lang=ZH-CN style='font-family:楷体'>,则可执行</span><span> make run-matrix </span><span
lang=ZH-CN style='font-family:楷体'>命令来单独调试它。大致执行结果可看附录。(<b><span
style='color:red'>使用的是</span></b></span><b><span style='color:red'>qemu-1.0.1</span></b><span
lang=ZH-CN style='font-family:楷体'>)。</span></p>
<p class=MsoNormal style='margin-right:34.95pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><b><span lang=ZH-CN style='font-family:
楷体;color:red'>扩展练习</span></b><b><span style='color:red'>Challenge</span></b><b><span
lang=ZH-CN style='font-family:楷体;color:red'>:实现</span></b><b><span
style='color:red'>Linux</span></b><b><span lang=ZH-CN style='font-family:楷体;
color:red'></span></b><b><span style='color:red'>RCU</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'></span><span>ucore
</span><span lang=ZH-CN style='font-family:楷体'>下实现下</span><span>Linux</span><span
lang=ZH-CN style='font-family:楷体'></span><span>RCU</span><span lang=ZH-CN
style='font-family:楷体'>同步互斥机制。可阅读相关</span><span>Linux</span><span lang=ZH-CN
style='font-family:楷体'>内核书籍或查询网上资料,可了解</span><span>RCU</span><span lang=ZH-CN
style='font-family:楷体'>的细节,然后大致实现在</span><span>ucore</span><span lang=ZH-CN
style='font-family:楷体'>中。下面是一些参考资料:</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><a href="http://www.ibm.com/developerworks/cn/linux/l-rcu/"><span
style='color:windowtext;text-decoration:none'>http://www.ibm.com/developerworks/cn/linux/l-rcu/</span></a></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><a
href="http://www.diybl.com/course/6_system/linux/Linuxjs/20081117/151814.html"><span
style='color:windowtext;text-decoration:none'>http://www.diybl.com/course/6_system/linux/Linuxjs/20081117/151814.html</span></a></p>
<p class=MsoNormal style='margin-left:6.5pt;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=150 style='text-indent:24.0pt'><span lang=ZH-CN style='line-height:
150%;font-family:楷体'>此次实验中,主要有如下一些需要关注的文件:</span></p>
<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=493 valign=top style='width:492.65pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal><span style='font-size:10.0pt'>.</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>├── boot</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>├── kern</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── driver</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── fs</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── init</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── libs</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── mm</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── ......</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>vmm.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
└── <span style='color:#333399'>vmm.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── process</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>proc.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>proc.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
└──......</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── schedule</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── sync</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:red'>check_sync.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:red'>monitor.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:red'>monitor.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:red'>sem.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:red'>sem.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>sync.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:red'>wait.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
└── <span style='color:red'>wait.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── syscall</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>syscall.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
└──......</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'></span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
└── trap</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>├── libs</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>└── user</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── <span
style='color:#333399'>forktree.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── libs</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>   </span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├──<span style='color:#333399'> syscall.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>   </span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>syscall.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>   </span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>ulib.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>   </span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
├── <span style='color:#333399'>ulib.h</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>   </span><span
style='font-size:10.0pt'>&nbsp;&nbsp;</span><span style='font-size:10.0pt'>
└── ......</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── <span
style='color:#333399'>priority.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── <span
style='color:red'>sleep.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── <span
style='color:red'>sleepkill.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── softint.c</span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    ├── <span
style='color:#333399'>spin.c</span></span></p>
<p class=MsoNormal><span style='font-size:10.0pt'>    └── ......</span></p>
</td>
</tr>
</table>
<p class=MsoNormal><span>&nbsp;</span></p>
<p class=MsoNormal style='line-height:150%'><span lang=ZH-CN style='line-height:
150%;font-family:楷体'>简单说明如下:</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>kern/sync/sync.h: </span><span lang=ZH-CN style='font-family:
楷体'>去除了</span><span>lock</span><span lang=ZH-CN style='font-family:楷体'>实现(这对于不抢占内核没用)。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>kern/sync/wait.[ch]: </span><span lang=ZH-CN
style='font-family:楷体'>定了为</span><span>wait</span><span lang=ZH-CN
style='font-family:楷体'>结构和</span><span>waitqueue</span><span lang=ZH-CN
style='font-family:楷体'>结构以及在此之上的函数,这是</span><span>ucore</span><span lang=ZH-CN
style='font-family:楷体'>中的信号量</span><span>semophore</span><span lang=ZH-CN
style='font-family:楷体'>机制和条件变量机制的基础,在本次实验中你需要了解其实现。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>kern/sync/sem.[ch]:</span><span lang=ZH-CN
style='font-family:楷体'>定义并实现了</span><span>ucore</span><span lang=ZH-CN
style='font-family:楷体'>中内核级信号量相关的数据结构和函数,本次试验中你需要了解其中的实现,并基于此完成内核级条件变量的设计与实现。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>user/ libs/ {syscall.[ch],ulib.[ch] }</span><span
lang=ZH-CN style='font-family:楷体'></span><span>kern/sync/syscall.c</span><span
lang=ZH-CN style='font-family:楷体'>:实现了进程</span><span>sleep</span><span
lang=ZH-CN style='font-family:楷体'>相关的系统调用的参数传递和调用关系。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>user/{ sleep.c,sleepkill.c}: </span><span lang=ZH-CN
style='font-family:楷体'>进程睡眠相关的一些测试用户程序。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>kern/sync/monitor.[ch]: </span><span lang=ZH-CN
style='font-family:楷体'>基于管程的条件变量的实现程序,在本次实验中是练习的一部分,要求完成。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>kern/sync/check_sync.c</span><span lang=ZH-CN
style='font-family:楷体'>:实现了基于管程的哲学家就餐问题,在本次实验中是练习的一部分,要求完成基于管程的哲学家就餐问题。</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>kern/mm/vmm.[ch]</span><span lang=ZH-CN style='font-family:
楷体'>:用信号量</span><span>mm_sem</span><span lang=ZH-CN style='font-family:楷体'>取代</span><span>mm_struct</span><span
lang=ZH-CN style='font-family:楷体'>中原有的</span><span>mm_lock</span><span
lang=ZH-CN style='font-family:楷体'>。(本次实验不用管)</span></p>
<p class=150 style='text-indent:0cm'><b><span style='font-size:10.5pt;
line-height:150%;font-family:"Times New Roman"'>&nbsp;</span></b></p>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:14.0pt;
font-family:楷体;letter-spacing:.05pt'>3   <span lang=ZH-CN>同步互斥的设计与实现</span></span></b></p>
<p class=MsoNormal style='margin-left:6.5pt;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='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>互斥是指某一资源同时只允许一个进程对其进行访问,具有唯一性和排它性,但互斥不用限制进程对资源的访问顺序,即访问可以是无序的。同步是指在进程间的执行必须严格按照规定的某种先后次序来运行,即访问是有序的,这种先后次序取决于要系统完成的任务需求。在进程写资源情况下,进程间要求满足互斥条件。在进程读资源情况下,可允许多个进程同时访问资源。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:18.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>实验七提供了多种同步互斥手段,包括中断控制、等待队列、信号量、管程机制(包含条件变量设计)等,并基于信号量实现了哲学家问题的执行过程。而练习是要求用管程机制实现哲学家问题的执行过程。在实现信号量机制和管程机制时,需要让无法进入临界区的进程睡眠,为此在</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>中设计了等待队列。当进程无法进入临界区(即无法获得信号量)时,可让进程进入等待队列,这时的进程处于等待状态(也可称为阻塞状态),从而会让实验六中的调度器选择一个处于就绪状态(即</span><span>RUNNABLE
STATE</span><span lang=ZH-CN style='font-family:楷体'>)的进程,进行进程切换,让新进程有机会占用</span><span>CPU</span><span
lang=ZH-CN style='font-family:楷体'>执行,从而让整个系统的运行更加高效。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:18.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>在实验七中的</span><span>ucore</span><span lang=ZH-CN style='font-family:楷体'>初始化过程,开始的执行流程都与实验六相同,直到执行到创建第二个内核线程</span><span>init_main</span><span
lang=ZH-CN style='font-family:楷体'>时,修改了</span><span>init_main</span><span
lang=ZH-CN style='font-family:楷体'>的具体执行内容,即增加了</span><span>check_sync</span><span
lang=ZH-CN style='font-family:楷体'>函数的调用,而位于</span><span>lab7/kern/sync/check_sync.c</span><span
lang=ZH-CN style='font-family:楷体'>中的</span><span>check_sync</span><span
lang=ZH-CN style='font-family:楷体'>函数可以理解为是实验七的起始执行点,是实验七的总控函数。进一步分析此函数,可以看到这个函数主要分为了两个部分,第一部分是实现基于信号量的哲学家问题,第二部分是实现基于管程的哲学家问题。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:18.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>对于</span><span>check_sync</span><span lang=ZH-CN style='font-family:楷体'>函数的第一部分,首先实现初始化了一个互斥信号量,然后<a
name="OLE_LINK1">创建了对应</a></span><span>5</span><span lang=ZH-CN
style='font-family:楷体'>个哲学家行为的</span><span>5</span><span lang=ZH-CN
style='font-family:楷体'>个信号量,并创建</span><span>5</span><span lang=ZH-CN
style='font-family:楷体'>个内核线程代表</span><span>5</span><span lang=ZH-CN
style='font-family:楷体'>个哲学家,每个内核线程完成了基于信号量的哲学家吃饭睡觉思考行为实现。这部分是给学生作为练习参考用的。学生可以看看信号量是如何实现的,已经如何利用信号量完成哲学家问题。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:18.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>对于</span><span>check_sync</span><span lang=ZH-CN style='font-family:楷体'>函数的第二部分,首先初始化了管程,然后又创建了</span><span>5</span><span
lang=ZH-CN style='font-family:楷体'>个内核线程代表</span><span>5</span><span lang=ZH-CN
style='font-family:楷体'>个哲学家,每个内核线程要完成基于管程的哲学家吃饭睡觉思考行为实现。这部分需要学生来具体完成。学生需要掌握如何用信号量来实现条件变量,以及包含条件变量的管程如何能够确保哲学家能够正常思考和吃饭。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:18.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='margin-left:6.5pt;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='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><b><span lang=ZH-CN style='font-family:楷体'>开关中断</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>根据操作系统原理的知识,我们知道如果没有在硬件级保证读内存</span><span>-</span><span lang=ZH-CN
style='font-family:楷体'>修改值</span><span>-</span><span lang=ZH-CN
style='font-family:楷体'>写回内存的原子性,我们只能通过复杂的软件来实现同步互斥操作。但由于有开关中断和</span><span>test_and_set_bit</span><span
lang=ZH-CN style='font-family:楷体'>等原子操作机器指令的存在,使得我们在实现同步互斥原语上可以大大简化。在</span><span>atomic.c</span><span
lang=ZH-CN style='font-family:楷体'>文件中实现的</span><span>test_and_set_bit</span><span
lang=ZH-CN style='font-family:楷体'>等原子操作。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'></span><span>ucore</span><span lang=ZH-CN style='font-family:楷体'>中提供的底层机制包括中断开关控制和</span><span>test_and_set</span><span
lang=ZH-CN style='font-family:楷体'>相关原子操作机器指令。</span><span>kern/sync.c</span><span
lang=ZH-CN style='font-family:楷体'>中实现的开关中断的控制函数</span><a name="OLE_LINK28"><a
name="OLE_LINK27"><a name="OLE_LINK26"><span>local_intr_save</span></a></a></a><span>(x)</span><span
lang=ZH-CN style='font-family:楷体'></span><span>local_intr_restore(x)</span><span
lang=ZH-CN style='font-family:楷体'>,它们是基于</span><span>kern/driver</span><span
lang=ZH-CN style='font-family:楷体'>文件下的</span><span>intr_enable()</span><span
lang=ZH-CN style='font-family:楷体'></span><span>intr_disable()</span><span
lang=ZH-CN style='font-family:楷体'>函数实现的。具体调用关系为:</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:40.85pt;border-collapse:collapse;border:none'>
<tr>
<td width=432 valign=top style='width:432.35pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p><span lang=ZH-CN style='font-family:楷体'>关中断:</span><span style='font-family:
"Times New Roman"'>local_intr_save<a name="OLE_LINK29"> <a name="OLE_LINK31"><a
name="OLE_LINK30">--&gt; </a>__intr_save --&gt; intr_disable --&gt; cli</a></a></span></p>
<p><span lang=ZH-CN style='font-family:楷体'>开中断:</span><span style='font-family:
"Times New Roman"'>local_intr_restore<a name="OLE_LINK33"><a name="OLE_LINK32">--&gt;</a>
__intr_restore --&gt; intr_enable --&gt; sti </a></span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>最终的</span><span>cli</span><span lang=ZH-CN style='font-family:楷体'></span><span>sti</span><span
lang=ZH-CN style='font-family:楷体'></span><span>x86</span><span lang=ZH-CN
style='font-family:楷体'>的机器指令,最终实现了关中断和开中断,即设置了</span><span>eflags</span><span
lang=ZH-CN style='font-family:楷体'>寄存器中与中断相关的位。通过关闭中断,可以防止对当前执行的控制流被其他中断事件处理所打断。既然不能中断,那也就意味着在内核运行的当前进程无法被打断或被从新调度,即实现了对临界区的互斥操作。所以在单处理器情况下,可以通过开关中断实现对临界区的互斥保护,需要互斥的临界区代码的一般写法为:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:40.85pt;border-collapse:collapse;border:none'>
<tr>
<td width=432 valign=top style='width:432.35pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p><span style='font-size:10.0pt;font-family:Courier'>local_intr_save<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
</span><b>{</b><span style='color:gray'><br>
&nbsp;&nbsp;</span></span><span lang=ZH-CN style='font-size:10.0pt'>临界区代码</span></p>
<p><b><span style='font-size:10.0pt;font-family:Courier'>}</span></b><span
style='font-size:10.0pt;font-family:Courier;color:gray'><br>
</span><span style='font-size:10.0pt;font-family:Courier'>local_intr_restore<b>(</b>intr_flag<b>);</b></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>……</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>由于目前</span><span>ucore</span><span lang=ZH-CN style='font-family:楷体'>只实现了对单处理器的支持,所以通过这种方式,就可简单地支撑互斥操作了。在多处理器情况下,这种方法是无法实现互斥的,因为屏蔽了一个</span><span>CPU</span><span
lang=ZH-CN style='font-family:楷体'>的中断,只能阻止本</span><span>CPU</span><span
lang=ZH-CN style='font-family:楷体'>上的进程不会被中断或调度,并不意味着其他</span><span>CPU</span><span
lang=ZH-CN style='font-family:楷体'>上执行的进程不能执行临界区的代码。所以,开关中断只对单处理器下的互斥操作起作用。在本实验中,开关中断机制是实现信号量等高层同步互斥原语的底层支撑基础之一。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><b><span lang=ZH-CN style='font-family:楷体'>等待队列</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>到目前为止,我们的实验中,用户进程或内核线程还没有睡眠的支持机制。在课程中提到用户进程或内核线程可以转入休眠状态以等待某个特定事件,当该事件发生时这些进程能够被再次唤醒。内核实现这一功能的一个底层支撑机制就是等待队列(</span><span>wait
queue</span><span lang=ZH-CN style='font-family:楷体'>),等待队列和每一个事件(睡眠结束、时钟到达、任务完成、资源可用等)联系起来。需要等待事件的进程在转入休眠状态后插入到等待队列中。当事件发生之后,内核遍历相应等待队列,唤醒休眠的用户进程或内核线程,并设置其状态为就绪状态(</span><span>runnable
state</span><span lang=ZH-CN style='font-family:楷体'>),并将该进程从等待队列中清除。</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'></span><span>kern/sync/<span>{</span>
wait.h, wait.c<span> }</span></span><span lang=ZH-CN style='font-family:楷体'>中实现了</span><span>wait</span><span
lang=ZH-CN style='font-family:楷体'>结构和</span><span>wait queue</span><span
lang=ZH-CN style='font-family:楷体'>结构以及相关函数),这是实现</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>中的信号量机制和条件变量机制的基础,进入</span><span>wait queue</span><span
lang=ZH-CN style='font-family:楷体'>的进程会被设为睡眠状态,直到他们被唤醒。</span></p>
<div style='border:solid windowtext 1.0pt;padding:1.0pt 0cm 1.0pt 4.0pt'>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>typedef
 struct {</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
struct proc_struct *proc;     //</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>等待进程的指针</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
uint32_t wakeup_flags;               //</span><span lang=ZH-CN
style='font-size:10.5pt;font-family:楷体'>进程被放入等待队列的原因标记</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
wait_queue_t *wait_queue;   //</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>指向此</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>结构所属于的</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait_queue</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
list_entry_t wait_link;         //</span><span lang=ZH-CN style='font-size:
10.5pt;font-family:楷体'>用来组织</span><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait_queue</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'></span><span style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>节点的连接</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>}
wait_t;</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>typedef
struct {</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
list_entry_t wait_head;        //wait_queue</span><span lang=ZH-CN
style='font-size:10.5pt;font-family:楷体'>的队头</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>}
wait_queue_t;</span></p>
<p class=150 style='text-indent:3.15pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>le2wait(le,
member)                         //</span><span lang=ZH-CN style='font-size:
10.5pt;font-family:楷体'>实现</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>wait_t</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>中成员的指针向</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait_t </span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>指针的转化</span></p>
</div>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'></span><span>wait</span><span
lang=ZH-CN style='font-family:楷体'></span><span>wait queue</span><span
lang=ZH-CN style='font-family:楷体'>相关的函数主要分为两层,底层函数是对</span><span>wait queue</span><span
lang=ZH-CN style='font-family:楷体'>的初始化、插入、删除和查找操作,相关函数如下:</span></p>
<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=493 valign=top style='width:492.65pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wait_init(wait_t *wait, struct proc_struct *proc);   
//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>初始化</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>结构</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>bool wait_in_queue(wait_t *wait);                         
//wait</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>是否在</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'></span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wait_queue_init(wait_queue_t *queue);                
//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>初始化</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait_queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>结构</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wait_queue_add(wait_queue_t *queue, wait_t *wait);   
//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'></span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>前插到</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'></span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wait_queue_del(wait_queue_t *queue, wait_t *wait);   
//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'></span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>中删除</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait_t *wait_queue_next(wait_queue_t *queue, wait_t
*wait);//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>取得</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>的后一个链接指针</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait_t *wait_queue_prev(wait_queue_t *queue, wait_t
*wait);//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>取得</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>的前一个链接指针</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait_t *wait_queue_first(wait_queue_t *queue);            
//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>取得</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>的第一个</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait_t *wait_queue_last(wait_queue_t *queue);             
//</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>取得</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>的最后一个</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>bool wait_queue_empty(wait_queue_t *queue);               
//wait queue</span><span lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>是否为空</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span style='font-size:10.5pt'>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>高层函数基于底层函数实现了让进程进入等待队列,以及从等待队列中唤醒进程,相关函数如下:</span></p>
<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=493 valign=top style='width:492.65pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:9.0pt;font-family:
"Times New Roman"'>//</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'></span><span style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>与进程关联,且让当前进程关联的</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>进入等待队列</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>,当前进程睡眠</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wait_current_set(wait_queue_t *queue, wait_t *wait,
uint32_t wait_state);</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>//</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>把与当前进程关联的</span><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>从等待队列</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>queue</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>中删除</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait_current_del(queue, wait);</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>//</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>唤醒与</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>wait</span><span
lang=ZH-CN style='font-size:10.5pt;font-family:楷体'>关联的进程</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wakeup_wait(wait_queue_t *queue, wait_t *wait,
uint32_t wakeup_flags, bool del);</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>//</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>唤醒等待队列上挂着的第一个</span><span style='font-size:10.5pt;font-family:
"Times New Roman"'>wait</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>所关联的进程</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wakeup_first(wait_queue_t *queue, uint32_t
wakeup_flags, bool del);</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>//</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>唤醒等待队列上所有的等待的进程</span></p>
<p class=150 style='text-align:justify;text-justify:inter-ideograph;
text-indent:0cm;line-height:normal'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>void wakeup_queue(wait_queue_t *queue, uint32_t
wakeup_flags, bool del);</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><b><span style='font-size:14.0pt'>&nbsp;</span></b></p>
<p class=MsoNormal style='margin-left:6.5pt;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='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>信号量是一种同步互斥机制的实现,普遍存在于现在的各种操作系统内核里。相对于</span><span>spinlock
</span><span lang=ZH-CN style='font-family:楷体'>的应用对象,信号量的应用对象是在临界区中运行的时间较长的进程。等待信号量的进程需要睡眠来减少占用</span><span>
CPU </span><span lang=ZH-CN style='font-family:楷体'>的开销。参考教科书“</span><span>Operating
Systems Internals and Design Principles</span><span lang=ZH-CN
style='font-family:楷体'>”第五章“同步互斥”中对信号量实现的原理性描述:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=534 valign=top style='width:534.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>struct semaphore {</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>int count;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>queueType queue;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>};</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>void semWait(semaphore s)</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>{</span></p>
<p class=MsoNormal style='margin-left:36.0pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><span>s.count--;</span></p>
<p class=MsoNormal style='margin-left:36.0pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><span>if (s.count &lt; 0) {</span></p>
<p class=MsoNormal style='margin-left:36.0pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><span>/* place this process in s.queue
*/;</span></p>
<p class=MsoNormal style='margin-left:36.0pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><span>/* block this process */;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:36.0pt;text-autospace:none'><span>}</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>}</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>void semSignal(semaphore s)</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>{</span></p>
<p class=MsoNormal style='margin-left:24.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:12.0pt;text-autospace:none'><span>s.count++;</span></p>
<p class=MsoNormal style='margin-left:24.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:12.0pt;text-autospace:none'><span>if
(s.count&lt;= 0) {</span></p>
<p class=MsoNormal style='margin-left:24.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:12.0pt;text-autospace:none'><span>/* remove a
process P from s.queue */;</span></p>
<p class=MsoNormal style='margin-left:24.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:12.0pt;text-autospace:none'><span>/* place
process P on ready list */;</span></p>
<p class=MsoNormal style='margin-left:24.0pt;text-align:justify;text-justify:
inter-ideograph;text-indent:12.0pt;text-autospace:none'><span>}</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>}</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>基于上诉信号量实现可以认为,当多个(</span><span>&gt;1</span><span lang=ZH-CN
style='font-family:楷体'>)进程可以进行互斥或同步合作时,一个进程会由于无法满足信号量设置的某条件而在某一位置停止,直到它接收到一个特定的信号(表明条件满足了)。为了发信号,需要使用一个称作信号量的特殊变量。为通过信号量</span><span>s</span><span
lang=ZH-CN style='font-family:楷体'>传送信号,信号量的</span><span>V</span><span
lang=ZH-CN style='font-family:楷体'>操作采用进程可执行原语</span><span>semSignal(s) </span><span
lang=ZH-CN style='font-family:楷体'>;为通过信号量</span><span>s</span><span lang=ZH-CN
style='font-family:楷体'>接收信号,信号量的</span><span>P</span><span lang=ZH-CN
style='font-family:楷体'>操作采用进程可执行原语</span><span>semWait(s ) </span><span
lang=ZH-CN style='font-family:楷体'>;如果相应的信号仍然没有发送,则进程被阻塞或睡眠,直到发送完为止。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>ucore</span><span lang=ZH-CN style='font-family:
楷体'>中信号量参照上述原理描述,建立在开关中断机制和</span><span>wait queue</span><span lang=ZH-CN
style='font-family:楷体'>的基础上进行了具体实现。信号量的数据结构定义如下:</span></p>
<div style='border:solid windowtext 1.0pt;padding:1.0pt 4.0pt 1.0pt 4.0pt'>
<p class=150 style='text-indent:1.65pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>typedef
struct {</span></p>
<p class=150 style='text-indent:1.65pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
int value;                           //</span><span lang=ZH-CN
style='font-size:10.5pt;font-family:楷体'>信号量的当前值</span></p>
<p class=150 style='text-indent:1.65pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>   
wait_queue_t wait_queue;     //</span><span lang=ZH-CN style='font-size:10.5pt;
font-family:楷体'>信号量对应的等待队列</span></p>
<p class=150 style='text-indent:1.65pt;line-height:normal;border:none;
padding:0cm'><span style='font-size:10.5pt;font-family:"Times New Roman"'>}
semaphore_t;</span></p>
</div>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:21.0pt;text-autospace:none'><span style='font-size:10.5pt'>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>semaphore_t</span><span
lang=ZH-CN style='font-family:楷体'>是最基本的记录型信号量(</span><span>record semaphore)</span><span
lang=ZH-CN style='font-family:楷体'>结构,包含了用于计数的整数值</span><span>value</span><span
lang=ZH-CN style='font-family:楷体'>,和一个进程等待队列</span><span>wait_queue</span><span
lang=ZH-CN style='font-family:楷体'>,一个等待的进程会挂在此等待队列上。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'></span><span>ucore</span><span lang=ZH-CN style='font-family:楷体'>中最重要的信号量操作是</span><span>P</span><span
lang=ZH-CN style='font-family:楷体'>操作函数</span><span>down(semaphore_t *sem)</span><span
lang=ZH-CN style='font-family:楷体'></span><span>V</span><span lang=ZH-CN
style='font-family:楷体'>操作函数</span><span> up(semaphore_t *sem)</span><span
lang=ZH-CN style='font-family:楷体'>。但这两个函数的具体实现是</span><span>__down(semaphore_t
*sem, uint32_t wait_state) </span><span lang=ZH-CN style='font-family:楷体'>函数和</span><span>__up(semaphore_t
*sem, uint32_t wait_state)</span><span lang=ZH-CN style='font-family:楷体'>函数,二者的具体实现描述如下:</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>__down(semaphore_t *sem, uint32_t wait_state, timer_t
*timer)</span><span lang=ZH-CN style='font-family:楷体'>:具体实现信号量的</span><span>P</span><span
lang=ZH-CN style='font-family:楷体'>操作,首先关掉中断,然后判断当前信号量的</span><span>value</span><span
lang=ZH-CN style='font-family:楷体'>是否大于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>。如果是</span><span>&gt;0</span><span lang=ZH-CN
style='font-family:楷体'>,则表明可以获得信号量,故让</span><span>value</span><span lang=ZH-CN
style='font-family:楷体'>减一,并打开中断返回即可;如果不是</span><span>&gt;0</span><span
lang=ZH-CN style='font-family:楷体'>,则表明无法获得信号量,故需要将当前的进程加入到等待队列中,并打开中断,然后运行调度器选择另外一个进程执行。如果被</span><span>V</span><span
lang=ZH-CN style='font-family:楷体'>操作唤醒,则把自身关联的</span><span>wait</span><span
lang=ZH-CN style='font-family:楷体'>从等待队列中删除(此过程需要先关中断,完成后开中断)。具体实现如下所示:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:39.0pt;border-collapse:collapse;border:none'>
<tr>
<td width=534 valign=top style='width:534.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p style='margin-left:18.0pt'><b><span style='font-size:10.0pt;font-family:
Courier;color:navy'>static</span></b><span style='font-size:10.0pt;
font-family:Courier;color:gray'>&nbsp;</span><span style='font-size:10.0pt;
font-family:Courier'>__noinline<span style='color:gray'>&nbsp;</span>uint32_t<span
style='color:gray'>&nbsp;</span>__down<b>(</b>semaphore_t<span
style='color:gray'>&nbsp;</span><b>*</b>sem<b>,</b><span style='color:gray'>&nbsp;</span>uint32_t<span
style='color:gray'>&nbsp;</span>wait_state<b>)</b><span style='color:gray'>&nbsp;</span><b>{</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>bool<span style='color:gray'>&nbsp;</span>intr_flag<b>;</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_save<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span style='color:navy'>if</span></b><span
style='color:gray'>&nbsp;</span><b>(</b>sem<b>-&gt;</b>value<span
style='color:gray'>&nbsp;</span><b>&gt;</b><span style='color:gray'>&nbsp;</span><span
style='color:teal'>0</span><b>)</b><span style='color:gray'>&nbsp;</span><b>{</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>sem<b>-&gt;</b>value<span
style='color:gray'>&nbsp;</span><b>--;</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_restore<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span
style='color:navy'>return</span></b><span style='color:gray'>&nbsp;</span><span
style='color:teal'>0</span><b>;</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b>}</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>wait_t<span style='color:gray'>&nbsp;</span>__wait<b>,</b><span
style='color:gray'>&nbsp;</span><b>*</b>wait<span style='color:gray'>&nbsp;</span><b>=</b><span
style='color:gray'>&nbsp;</span><b>&amp;</b>__wait<b>;</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>wait_current_set<b>(&amp;(</b>sem<b>-&gt;</b>wait_queue<b>),</b><span
style='color:gray'>&nbsp;</span>wait<b>,</b><span style='color:gray'>&nbsp;</span>wait_state<b>);</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_restore<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>schedule<b>();</b><span style='color:gray'><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_save<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>wait_current_del<b>(&amp;(</b>sem<b>-&gt;</b>wait_queue<b>),</b><span
style='color:gray'>&nbsp;</span>wait<b>);</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_restore<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span style='color:navy'>if</span></b><span
style='color:gray'>&nbsp;</span><b>(</b>wait<b>-&gt;</b>wakeup_flags<span
style='color:gray'>&nbsp;</span><b>!=</b><span style='color:gray'>&nbsp;</span>wait_state<b>)</b><span
style='color:gray'>&nbsp;</span><b>{</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span
style='color:navy'>return</span></b><span style='color:gray'>&nbsp;</span>wait<b>-&gt;</b>wakeup_flags<b>;</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b>}</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span style='color:navy'>return</span></b><span
style='color:gray'>&nbsp;</span><span style='color:teal'>0</span><b>;</b><span
style='color:gray'><br>
</span><b>}</b></span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>&nbsp;</span></p>
</td>
</tr>
</table>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:0cm;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:0cm;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>__up(semaphore_t *sem, uint32_t wait_state)</span><span
lang=ZH-CN style='font-family:楷体'>:具体实现信号量的</span><span>V</span><span
lang=ZH-CN style='font-family:楷体'>操作,首先关中断,如果信号量对应的</span><span>wait queue</span><span
lang=ZH-CN style='font-family:楷体'>中没有进程在等待,直接把信号量的</span><span>value</span><span
lang=ZH-CN style='font-family:楷体'>加一,然后开中断返回;如果有进程在等待且进程等待的原因是</span><span>semophore</span><span
lang=ZH-CN style='font-family:楷体'>设置的,则调用</span><span>wakeup_wait</span><span
lang=ZH-CN style='font-family:楷体'>函数将</span><span>waitqueue</span><span
lang=ZH-CN style='font-family:楷体'>中等待的第一个</span><span>wait</span><span
lang=ZH-CN style='font-family:楷体'>删除,且把此</span><span>wait</span><span
lang=ZH-CN style='font-family:楷体'>关联的进程唤醒,最后开中断返回。具体实现如下所示:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:39.0pt;border-collapse:collapse;border:none'>
<tr>
<td width=534 valign=top style='width:534.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p style='margin-left:18.0pt'><b><span style='font-size:10.0pt;font-family:
Courier;color:navy'>static</span></b><span style='font-size:10.0pt;
font-family:Courier;color:gray'>&nbsp;</span><span style='font-size:10.0pt;
font-family:Courier'>__noinline<span style='color:gray'>&nbsp;</span><b><span
style='color:navy'>void</span></b><span style='color:gray'>&nbsp;</span>__up<b>(</b>semaphore_t<span
style='color:gray'>&nbsp;</span><b>*</b>sem<b>,</b><span style='color:gray'>&nbsp;</span>uint32_t<span
style='color:gray'>&nbsp;</span>wait_state<b>)</b><span style='color:gray'>&nbsp;</span><b>{</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>bool<span style='color:gray'>&nbsp;</span>intr_flag<b>;</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_save<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b>{</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>wait_t<span
style='color:gray'>&nbsp;</span><b>*</b>wait<b>;</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span
style='color:navy'>if</span></b><span style='color:gray'>&nbsp;</span><b>((</b>wait<span
style='color:gray'>&nbsp;</span><b>=</b><span style='color:gray'>&nbsp;</span>wait_queue_first<b>(&amp;(</b>sem<b>-&gt;</b>wait_queue<b>)))</b><span
style='color:gray'>&nbsp;</span><b>==</b><span style='color:gray'>&nbsp;</span>NULL<b>)</b><span
style='color:gray'>&nbsp;</span><b>{</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>sem<b>-&gt;</b>value<span
style='color:gray'>&nbsp;</span><b>++;</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><b>}</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><b><span
style='color:navy'>else</span></b><span style='color:gray'>&nbsp;</span><b>{</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>wakeup_wait<b>(&amp;(</b>sem<b>-&gt;</b>wait_queue<b>),</b><span
style='color:gray'>&nbsp;</span>wait<b>,</b><span style='color:gray'>&nbsp;</span>wait_state<b>,</b><span
style='color:gray'>&nbsp;</span><span style='color:teal'>1</span><b>);</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><b>}</b><span
style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span><b>}</b><span style='color:gray'><br>
&nbsp;&nbsp;&nbsp;&nbsp;</span>local_intr_restore<b>(</b>intr_flag<b>);</b><span
style='color:gray'><br>
</span><b>}</b></span></p>
</td>
</tr>
</table>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:0cm;text-autospace:none'><span>&nbsp;</span></p>
<p class=150 style='text-indent:24.0pt'><span lang=ZH-CN style='line-height:
150%;font-family:楷体'>对照信号量的原理性描述和具体实现,可以发现二者在流程上基本一致,只是具体实现采用了关中断的方式保证了对共享资源的互斥访问,通过等待队列让无法获得信号量的进程睡眠等待。另外,我们可以看出信号量的计数器</span><span
style='line-height:150%;font-family:"Times New Roman"'>value</span><span
lang=ZH-CN style='line-height:150%;font-family:楷体'>具有有如下性质:</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>value&gt;0</span><span lang=ZH-CN style='font-family:楷体'>,表示共享资源的空闲数</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>vlaue&lt;0</span><span lang=ZH-CN style='font-family:楷体'>,表示该信号量的等待队列里的进程数</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span>value=0</span><span lang=ZH-CN style='font-family:楷体'>,表示等待队列为空</span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:0cm;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='margin-left:6.5pt;text-autospace:none'><b><span
style='font-size:14.0pt'>3.4 </span></b><b><span lang=ZH-CN style='font-size:
14.0pt;font-family:楷体'>管程和条件变量</span></b></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>引入了管程是为了将对共享资源的所有访问及其所需要的同步操作集中并封装起来。</span><span>Hansan</span><span
lang=ZH-CN style='font-family:楷体'>为管程所下的定义:</span><span></span><span
lang=ZH-CN style='font-family:楷体'>一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据</span><span></span><span
lang=ZH-CN style='font-family:楷体'>。有上述定义可知,管程由四部分组成:</span><span lang=ZH-CN> </span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>管程内部的共享变量;</span><span
lang=ZH-CN> </span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>管程内部的条件变量;</span><span
lang=ZH-CN> </span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>管程内部并发执行的进程;</span><span
lang=ZH-CN> </span></p>
<p class=MsoListParagraph style='margin-left:39.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:"永中宋体","serif"'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=ZH-CN style='font-family:楷体'>对局部于管程内部的共享数据设置初始值的语句。</span><span
lang=ZH-CN> </span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>局限在管程中的数据结构,只能被局限在管程的操作过程所访问,任何管程之外的操作过程都不能访问它;另一方面,局限在管程中的操作过程也主要访问管程内的数据结构。由此可见,管程相当于一个隔离区,它把共享变量和对它进行操作的若干个过程围了起来,所有进程要访问临界资源时,都必须经过管程才能进入,而管程每次只允许一个进程进入管程,从而需要确保进程之间互斥。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>但在管程中仅仅有互斥操作是不够用的。进程可能需要等待某个条件</span><span>C</span><span lang=ZH-CN
style='font-family:楷体'>为真才能继续执行。如果采用</span><a
href="http://zh.wikipedia.org/w/index.php?title=%E5%BF%99%E7%AD%89%E5%BE%85&amp;action=edit&amp;redlink=1"
title="忙等待(页面不存在)"><span lang=ZH-CN style='font-family:楷体;color:windowtext;
text-decoration:none'>忙等</span></a><span>(busy waiting)</span><span lang=ZH-CN
style='font-family:楷体'>方式:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:40.85pt;border-collapse:collapse;border:none'>
<tr>
<td width=475 valign=top style='width:474.85pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>   while not( C ) do {}</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>在单处理器情况下,将会导致所有其它进程都无法进入</span><a
href="http://zh.wikipedia.org/wiki/%E4%B8%B4%E7%95%8C%E5%8C%BA" title=临界区><span
lang=ZH-CN style='font-family:楷体;color:windowtext;text-decoration:none'>临界区</span></a><span
lang=ZH-CN style='font-family:楷体'>使得该条件</span><span>C</span><span lang=ZH-CN
style='font-family:楷体'>为真,该管程的执行将会发生</span><a
href="http://zh.wikipedia.org/wiki/%E6%AD%BB%E9%94%81" title=死锁><span
lang=ZH-CN style='font-family:楷体;color:windowtext;text-decoration:none'>死锁</span></a><span
lang=ZH-CN style='font-family:楷体'>。为此,可引入条件变量(</span><span>Condition Variables</span><span
lang=ZH-CN style='font-family:楷体'>,简称</span><span>CV</span><span lang=ZH-CN
style='font-family:楷体'>)。一个条件变量</span><span>CV</span><span lang=ZH-CN
style='font-family:楷体'>可理解为一个进程的等待队列,队列中的进程正等待某个条件</span><span>C</span><span
lang=ZH-CN style='font-family:楷体'>变为真。每个条件变量关联着一个</span><a
href="http://zh.wikipedia.org/wiki/%E6%96%B7%E8%A8%80_(%E7%A8%8B%E5%BC%8F)"
title="断言 (程序)"><span lang=ZH-CN style='font-family:楷体;color:windowtext;
text-decoration:none'>断言</span></a><span>Pc</span><span lang=ZH-CN
style='font-family:楷体'>。当一个进程等待一个条件变量,该进程不算作占用了该管程,因而其它进程可以进入该管程执行,改变管程的状态,通知条件变量</span><span>CV</span><span
lang=ZH-CN style='font-family:楷体'>其关联的断言</span><span>Pc</span><span lang=ZH-CN
style='font-family:楷体'>在当前状态下为真。因此对条件变量</span><span>CV</span><span lang=ZH-CN
style='font-family:楷体'>有两种主要操作:</span></p>
<p class=MsoListParagraph style='margin-left:45.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:Wingdings'>l<span style='font:7.0pt "Times New Roman"'>&nbsp;
</span></span><span>wait_cv</span><span lang=ZH-CN style='font-family:楷体'></span><span>&nbsp;</span><span
lang=ZH-CN style='font-family:楷体'>被一个进程调用,以等待断言</span>Pc<span lang=ZH-CN
style='font-family:楷体'>被满足后该进程可恢复执行</span><span>. </span><span lang=ZH-CN
style='font-family:楷体'>进程挂在该条件变量上等待时,不被认为是占用了管程。</span></p>
<p class=MsoListParagraph style='margin-left:45.0pt;text-align:justify;
text-justify:inter-ideograph;text-indent:-21.0pt;text-autospace:none'><span
style='font-family:Wingdings'>l<span style='font:7.0pt "Times New Roman"'>&nbsp;
</span></span><span>signal_cv</span><span lang=ZH-CN style='font-family:楷体'>:被一个进程调用,以指出断言</span>Pc<span
lang=ZH-CN style='font-family:楷体'>现在为真,从而可以唤醒等待断言</span>Pc<span lang=ZH-CN
style='font-family:楷体'>被满足的进程继续执行。</span></p>
<p class=MsoNormal style='margin-left:24.0pt;text-align:justify;text-justify:
inter-ideograph;text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>有了互斥和信号量支持的管程就可用用了解决各种同步互斥问题。比如参考《</span><span>OS
Concept</span><span lang=ZH-CN style='font-family:楷体'>》一书中的</span><span>6.7.2</span><span
lang=ZH-CN style='font-family:楷体'>小节“用管程解决哲学家就餐问题”就给出了这样的事例:</span></p>
<p class=150 align=center style='margin-left:45.0pt;text-align:center;
text-indent:-21.0pt'><span style='font-size:10.5pt;line-height:150%;font-family:
Wingdings'>l<span style='font:7.0pt "Times New Roman"'>&nbsp; </span></span><span
style='font-size:10.5pt;line-height:150%;font-family:"Times New Roman"'><img
border=0 width=342 height=470 id="图片 7" src="lab7.files/image001.png"></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>虽然大部分教科书上说明管程适合在语言级实现比如</span><span>java</span><span lang=ZH-CN
style='font-family:楷体'>等高级语言,没有提及在采用</span><span>C</span><span lang=ZH-CN
style='font-family:楷体'>语言的</span><span>OS</span><span lang=ZH-CN
style='font-family:楷体'>中如何实现。下面我们将要尝试在</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>中用</span><span>C</span><span lang=ZH-CN
style='font-family:楷体'>语言实现采用基于互斥和条件变量机制的管程基本原理。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>ucore</span><span lang=ZH-CN
style='font-family:楷体'>中的管程机制是基于信号量和条件变量来实现的。</span><span>ucore</span><span
lang=ZH-CN style='font-family:楷体'>中的管程的数据结构</span><span>monitor_t</span><span
lang=ZH-CN style='font-family:楷体'>定义如下:</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=534 valign=top style='width:534.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:
9.0pt'>typedef</span></b><span style='font-size:9.0pt'> <b>struct</b> <span
style='background:lightgrey'>monitor</span>{</span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt'>   
semaphore_t mutex;      // the <u>mutex</u> lock for going into the routines
in monitor, should be initialized to 1</span></p>
<p class=MsoNormal style='text-indent:18.0pt;text-autospace:none'><span
style='font-size:9.0pt'>semaphore_t next;       // the next semaphore is used
to down the signaling <u>proc</u> itself, and the other OR <u>wakeuped</u> </span></p>
<p class=MsoNormal style='text-indent:117.0pt;text-autospace:none'><span
style='font-size:9.0pt'>//waiting <u>proc</u> should wake up the <u>sleeped</u>
signaling <u>proc</u>.</span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt'>   
<b>int</b> next_count;         // the number of of <u>sleeped</u> signaling <u>proc</u></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt'>   
condvar_t *cv;          // the <u>condvars</u> in monitor</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span style='font-size:9.0pt'>} monitor_t;</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>管程中的成员变量</span><span>mutex</span><span lang=ZH-CN style='font-family:楷体'>是一个二值信号量,是实现每次只允许一个进程进入管程的关键元素,确保了</span><a
href="http://zh.wikipedia.org/wiki/%E4%BA%92%E6%96%A5" title=互斥><span
lang=ZH-CN style='font-family:楷体;color:windowtext;text-decoration:none'>互斥</span></a><span
lang=ZH-CN style='font-family:楷体'>访问性质。管程中的条件变量</span><span>cv</span><span
lang=ZH-CN style='font-family:楷体'>通过执行</span><span>wait_cv</span><span
lang=ZH-CN style='font-family:楷体'>,会使得等待某个条件</span><span>C</span><span
lang=ZH-CN style='font-family:楷体'>为真的进程能够离开管程并睡眠,且让其他进程进入管程继续执行;而进入管程的某进程设置条件</span><span>C</span><span
lang=ZH-CN style='font-family:楷体'>为真并执行</span><span>signal_cv</span><span
lang=ZH-CN style='font-family:楷体'>时,能够让等待某个条件</span><span>C</span><span
lang=ZH-CN style='font-family:楷体'>为真的睡眠进程被唤醒,从而继续进入管程中执行。管程中的成员变量信号量</span><span>next</span><span
lang=ZH-CN style='font-family:楷体'>和整形变量</span><span>next_count</span><span
lang=ZH-CN style='font-family:楷体'>是配合进程对条件变量</span><span>cv</span><span
lang=ZH-CN style='font-family:楷体'>的操作而设置的,这是由于发出</span><span>signal_cv</span><span
lang=ZH-CN style='font-family:楷体'>的进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>会唤醒睡眠进程</span><span>B</span><span lang=ZH-CN
style='font-family:楷体'>,进程</span><span>B</span><span lang=ZH-CN
style='font-family:楷体'>执行会导致进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>睡眠,直到进程</span><span>B</span><span lang=ZH-CN
style='font-family:楷体'>离开管程,进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>才能继续执行,这个同步过程是通过信号量</span><span>next</span><span
lang=ZH-CN style='font-family:楷体'>完成的;而</span><span>next_count</span><span
lang=ZH-CN style='font-family:楷体'>表示了由于发出</span><span>singal_cv</span><span
lang=ZH-CN style='font-family:楷体'>而睡眠的进程个数。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>管程中的条件变量的数据结构</span><span>condvar_t</span><span lang=ZH-CN
style='font-family:楷体'>定义如下:</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=534 valign=top style='width:534.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:
10.0pt'>typedef</span></b><span style='font-size:10.0pt'> <b>struct</b>
condvar{</span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:10.0pt'>   
semaphore_t sem; // the <u>sem</u> semaphore is used to down the waiting <u>proc</u>,
and the signaling <u>proc</u> should up the waiting <u>proc</u></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:10.0pt'>   
<b>int</b> count;       // the number of waiters on <u>condvar</u></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:10.0pt'>   
monitor_t * owner; // the owner(monitor) of this <u>condvar</u></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:10.0pt'>}
condvar_t;</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>条件变量的定义中也包含了一系列的成员变量,信号量</span><span>sem</span><span lang=ZH-CN
style='font-family:楷体'>用于让发出</span><span>wait_cv</span><span lang=ZH-CN
style='font-family:楷体'>操作的等待某个条件</span><span>C</span><span lang=ZH-CN
style='font-family:楷体'>为真的进程睡眠,而让发出</span><span>signal_cv</span><span
lang=ZH-CN style='font-family:楷体'>操作的进程通过这个</span><span>sem</span><span
lang=ZH-CN style='font-family:楷体'>来唤醒睡眠的进程。</span><span>count</span><span
lang=ZH-CN style='font-family:楷体'>表示等在这个条件变量上的睡眠进程的个数。</span><span>owner</span><span
lang=ZH-CN style='font-family:楷体'>表示此条件变量的宿主是哪个管程。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>理解了数据结构的含义后,我们就可以开始管程的实现了。</span><span>ucore</span><span lang=ZH-CN
style='font-family:楷体'>设计实现了条件变量</span><span>wait_cv</span><span lang=ZH-CN
style='font-family:楷体'>操作和</span><span>signal_cv</span><span lang=ZH-CN
style='font-family:楷体'>操作对应的具体函数,即</span><span>cond_wait</span><span
lang=ZH-CN style='font-family:楷体'>函数和</span><span>cond_signal</span><span
lang=ZH-CN style='font-family:楷体'>函数,此外还有</span><span>cond_init</span><span
lang=ZH-CN style='font-family:楷体'>初始化函数(可直接看源码)。函数</span><span>cond_wait(condvar_t
*cvp, semaphore_t *mp)</span><span lang=ZH-CN style='font-family:楷体'></span><span>cond_signal
(condvar_t *cvp)</span><span lang=ZH-CN style='font-family:楷体'>的实现原理可参考《</span><span>OS
Concept</span><span lang=ZH-CN style='font-family:楷体'>》一书中的</span><span>6.7.3</span><span
lang=ZH-CN style='font-family:楷体'>小节</span><span></span><span lang=ZH-CN
style='font-family:楷体'>用信号量实现管程</span><span></span><span lang=ZH-CN
style='font-family:楷体'>的内容:</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0 align=left
style='border-collapse:collapse;border:none;margin-left:6.0pt;margin-right:
6.0pt'>
<tr>
<td width=218 valign=top style='width:218.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal align=center style='text-align:center;text-autospace:none'><b><span
style='font-size:10.5pt'>cond_wait</span></b><b><span lang=ZH-CN
style='font-size:10.5pt;font-family:楷体'>的原理描述</span></b></p>
<p class=MsoNormal align=center style='text-align:center;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>cv.count++;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>if(monitor.next_count &gt; 0)</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>   sem_signal(monitor.next);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>else</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>   sem_signal(monitor.mutex);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>sem_wait(cv.sem);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>cv.count -- ;</span></p>
</td>
</tr>
</table>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0 align=left
style='border-collapse:collapse;border:none;margin-left:6.0pt;margin-right:
6.0pt'>
<tr style='height:127.3pt'>
<td width=218 valign=top style='width:218.05pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt;height:127.3pt'>
<p class=MsoNormal align=center style='text-align:center;text-autospace:none'><b><span
style='font-size:10.5pt'>ond_signal</span></b><b><span lang=ZH-CN
style='font-size:10.5pt;font-family:楷体'>的原理描述</span></b></p>
<p class=MsoNormal align=center style='text-align:center;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>if( cv.count &gt; 0) {</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>   monitor.next_count ++;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>   sem_signal(cv.sem);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>   sem_wait(monitor.next);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>   monitor.next_count -- ;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>}</span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>  </span><span lang=ZH-CN
style='font-family:楷体'>简单分析一下</span><span>cond_wait</span><span lang=ZH-CN
style='font-family:楷体'>函数的实现。可以看出如果进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>执行了</span><span>cond_wait</span><span lang=ZH-CN
style='font-family:楷体'>函数,表示此进程等待某个条件</span><span>C</span><span lang=ZH-CN
style='font-family:楷体'>不为真,需要睡眠。因此表示等待此条件的睡眠进程个数</span><span>cv.count</span><span
lang=ZH-CN style='font-family:楷体'>要加一。接下来会出现两种情况。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>情况一:如果</span><span>monitor.next_count</span><span lang=ZH-CN
style='font-family:楷体'>如果大于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>,表示有大于等于</span><span>1</span><span lang=ZH-CN
style='font-family:楷体'>个进程执行</span><span>cond_signal</span><span lang=ZH-CN
style='font-family:楷体'>函数且睡着了,就睡在了</span><span>monitor.next</span><span
lang=ZH-CN style='font-family:楷体'>信号量上。假定这些进程形成</span><span>S</span><span
lang=ZH-CN style='font-family:楷体'>进程链表。因此需要唤醒</span><span>S</span><span
lang=ZH-CN style='font-family:楷体'>进程链表中的一个进程</span><span>B</span><span
lang=ZH-CN style='font-family:楷体'>。然后进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>睡在</span><span>cv.sem</span><span lang=ZH-CN
style='font-family:楷体'>上,如果睡醒了,则让</span><span>cv.count</span><span lang=ZH-CN
style='font-family:楷体'>减一,表示等待此条件的睡眠进程个数少了一个,可继续执行了!这里隐含这一个现象,即某进程</span><span>A</span><span
lang=ZH-CN style='font-family:楷体'>在时间顺序上先执行了</span><span>signal_cv</span><span
lang=ZH-CN style='font-family:楷体'>,而另一个进程</span><span>B</span><span lang=ZH-CN
style='font-family:楷体'>后执行了</span><span>wait_cv</span><span lang=ZH-CN
style='font-family:楷体'>,这会导致进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>没有起到唤醒进程</span><span>B</span><span lang=ZH-CN
style='font-family:楷体'>的作用。这里还隐藏这一个问题,在</span><span>cond_wait</span><span
lang=ZH-CN style='font-family:楷体'></span><span>sem_signal(mutex)</span><span
lang=ZH-CN style='font-family:楷体'>,但没有看到哪里有</span><span>sem_wait(mutex)</span><span
lang=ZH-CN style='font-family:楷体'>,这好像没有成对出现,是否是错误的?其实在管程中的每一个函数的入口处会有</span><span>wait(mutex)</span><span
lang=ZH-CN style='font-family:楷体'>,这样二者就配好对了。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>情况二:如果</span><span>monitor.next_count</span><span lang=ZH-CN
style='font-family:楷体'>如果小于等于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>,表示目前没有进程执行</span><span>cond_signal</span><span
lang=ZH-CN style='font-family:楷体'>函数且睡着了,那需要唤醒的是由于互斥条件限制而无法进入管程的进程,所以要唤醒睡在</span><span>monitor.mutex</span><span
lang=ZH-CN style='font-family:楷体'>上的进程。然后进程</span><span>A</span><span
lang=ZH-CN style='font-family:楷体'>睡在</span><span>cv.sem</span><span lang=ZH-CN
style='font-family:楷体'>上,如果睡醒了,则让</span><span>cv.count</span><span lang=ZH-CN
style='font-family:楷体'>减一,表示等待此条件的睡眠进程个数少了一个,可继续执行了!</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>对照着再来看</span><span>cond_signal</span><span lang=ZH-CN style='font-family:
楷体'>的实现。首先进程</span><span>B</span><span lang=ZH-CN style='font-family:楷体'>判断</span><span>cv.count</span><span
lang=ZH-CN style='font-family:楷体'>,如果不大于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>,则表示当前没有执行</span><span>cond_wait</span><span lang=ZH-CN
style='font-family:楷体'>而睡眠的进程,因此就没有被唤醒的对象了,直接函数返回即可;如果大于</span><span>0</span><span
lang=ZH-CN style='font-family:楷体'>,这表示当前有执行</span><span>cond_wait</span><span
lang=ZH-CN style='font-family:楷体'>而睡眠的进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>,因此需要唤醒等待在</span><span>cv.sem</span><span lang=ZH-CN
style='font-family:楷体'>上睡眠的进程</span><span>A</span><span lang=ZH-CN
style='font-family:楷体'>。由于只允许一个进程在管程中执行,所以一旦进程</span><span>B</span><span
lang=ZH-CN style='font-family:楷体'>唤醒了别人(进程</span><span>A</span><span
lang=ZH-CN style='font-family:楷体'>),那么自己就需要睡眠。故让</span><span>monitor.next_count</span><span
lang=ZH-CN style='font-family:楷体'>加一,且让自己(进程</span><span>B</span><span
lang=ZH-CN style='font-family:楷体'>)睡在信号量</span><span>monitor.next</span><span
lang=ZH-CN style='font-family:楷体'>上。如果睡醒了,这让</span><span>monitor.next_count</span><span
lang=ZH-CN style='font-family:楷体'>减一。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>为了让整个管程正常运行,还需在管程中的每个函数的入口和出口增加相关操作,即:</span></p>
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0
style='margin-left:83.4pt;border-collapse:collapse;border:none'>
<tr>
<td width=333 valign=top style='width:333.1pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>function </span><span lang=ZH-CN style='font-family:
楷体'></span><span></span><span lang=ZH-CN style='font-family:楷体'></span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>{ </span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:12.0pt;text-autospace:none'><span>sem.wait(monitor.mutex);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>  </span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>  the real body of function;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>  </span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>  if(monitor.next_count &gt; 0) </span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>     sem_signal(monitor.next);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>  else</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>     sem_signal(monitor.mutex);</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span>} </span></p>
</td>
</tr>
</table>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span>&nbsp;</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-autospace:none'><span lang=ZH-CN style='font-family:楷体'>这样带来的作用有两个,(</span><span>1</span><span
lang=ZH-CN style='font-family:楷体'>)只有一个进程在执行管程中的函数。(</span><span>2</span><span
lang=ZH-CN style='font-family:楷体'>)避免由于执行了</span><span>cond_signal</span><span
lang=ZH-CN style='font-family:楷体'>函数而睡眠的进程无法被唤醒。对于第二点,如果进程</span><span>A</span><span
lang=ZH-CN style='font-family:楷体'>由于执行了</span><span>cond_signal</span><span
lang=ZH-CN style='font-family:楷体'>函数而睡眠(这会让</span><span>monitor.next_count</span><span
lang=ZH-CN style='font-family:楷体'>大于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>,且执行</span><span>sem_wait(monitor.next)</span><span
lang=ZH-CN style='font-family:楷体'>),则其他进程在执行管程中的函数的出口,会判断</span><span>monitor.next_count</span><span
lang=ZH-CN style='font-family:楷体'>是否大于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>,如果大于</span><span>0</span><span lang=ZH-CN
style='font-family:楷体'>,则执行</span><span>sem_signal(monitor.next)</span><span
lang=ZH-CN style='font-family:楷体'>,从而执行了</span><span>cond_signal</span><span
lang=ZH-CN style='font-family:楷体'>函数而睡眠的进程被唤醒。上诉措施将使得管程正常执行。</span></p>
<p class=MsoNormal style='text-align:justify;text-justify:inter-ideograph;
text-indent:24.0pt;text-autospace:none'><span lang=ZH-CN style='font-family:
楷体'>需要注意的是,上述只是原理描述,与具体描述相比,还有一定的差距。需要大家在完成练习时仔细设计和实现。</span></p>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:14.0pt;
letter-spacing:.05pt'>&nbsp;</span></b></p>
<p class=MsoNormal style='text-autospace:none'><b><span style='font-size:14.0pt;
letter-spacing:.05pt'>4 </span></b><b><span lang=ZH-CN style='font-size:14.0pt;
font-family:楷体;letter-spacing:.05pt'>实验报告要求</span></b></p>
<p class=MsoNormalIndent style='text-indent:25.5pt'><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>从网站上下载</span><span style='font-size:
12.0pt'>lab7.zip</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>后,解压得到本文档和代码目录</span><span style='font-size:12.0pt'> lab7</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'>
lab7-handin.tar.gz</span><span lang=ZH-CN style='font-size:12.0pt;font-family:
楷体'>。最后请一定提前或按时提交到网络学堂上。</span></p>
<p class=MsoNormalIndent style='text-indent:25.5pt'><span lang=ZH-CN
style='font-size:12.0pt;font-family:楷体'>注意有</span><span style='font-size:12.0pt'>“LAB7”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>的注释,主要是修改</span><span
style='font-size:12.0pt'>condvar.c</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'></span><span style='font-size:12.0pt'>check_sync.c</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>中的内容。代码中所有需要完成的地方</span><span
style='font-size:12.0pt'>challenge</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>除外)都有</span><span style='font-size:12.0pt'>“LAB7”</span><span
lang=ZH-CN style='font-size:12.0pt;font-family:楷体'></span><span
style='font-size:12.0pt'>“YOUR CODE”</span><span lang=ZH-CN style='font-size:
12.0pt;font-family:楷体'>的注释,请在提交时特别注意保持注释,并将</span><span style='font-size:12.0pt'>“YOUR
CODE”</span><span lang=ZH-CN style='font-size:12.0pt;font-family:楷体'>替换为自己的学号,并且将所有标有对应注释的部分填上正确的代码。</span></p>
<p class=150 style='text-indent:24.0pt'><span style='font-family:"Times New Roman"'>&nbsp;</span></p>
<p class=150 style='text-indent:0cm'><b><span lang=ZH-CN style='font-size:10.5pt;
line-height:150%;font-family:楷体'>附录:执行</span></b><b><span style='font-size:
10.5pt;line-height:150%;font-family:"Times New Roman"'>”make run-matrix”</span></b><b><span
lang=ZH-CN style='font-size:10.5pt;line-height:150%;font-family:楷体'>的大致的显示输出</span></b></p>
<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr>
<td width=493 valign=top style='width:492.65pt;border:solid windowtext 1.0pt;
padding:0cm 5.4pt 0cm 5.4pt'>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>(THU.CST) os is loading
...</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>……</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>check_alloc_page() succeeded!</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>……</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>check_swap() succeeded!</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>++ setup timer
interrupts</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>I am No.4
philosopher_condvar</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.4
philosopher_condvar is thinking</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>I am No.3
philosopher_condvar</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>……</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>I am No.1
philosopher_sema</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.1
philosopher_sema is thinking</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>I am No.0 philosopher_sema</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.0
philosopher_sema is thinking</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>kernel_execve: pid = 2,
name = “matrix”.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 14 is running (1000
times)!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 13 is running (1000
times)!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_test_condvar:
state_condvar[4] will eating</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_test_condvar:
signal self_cv[4] </span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.4
philosopher_condvar is eating</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_take_forks_condvar:
3 didnt get fork and will wait</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_test_condvar:
state_condvar[2] will eating</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_test_condvar:
signal self_cv[2] </span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.2
philosopher_condvar is eating</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_take_forks_condvar:
1 didnt get fork and will wait</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>phi_take_forks_condvar:
0 didnt get fork and will wait</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 14 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 13 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.4
philosopher_sema is eating</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Iter 1, No.2
philosopher_sema is eating</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>……</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 18 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 23 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 22 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 33 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 27 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 25 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 32 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 29 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>pid 20 done!.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>matrix pass.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>all user-mode processes
have quit.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>init check memory pass.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>kernel panic at
kern/process/proc.c:426:</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>    initproc exit.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>&nbsp;</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Welcome to the kernel
debug monitor!!</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>Type 'help' for a list
of commands.</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>K&gt; qemu: terminating
on signal 2</span></p>
<p class=150 style='text-indent:0cm;line-height:normal'><span
style='font-size:9.0pt;font-family:"Times New Roman"'>&nbsp;</span></p>
</td>
</tr>
</table>
<p class=150 style='text-indent:0cm'><span style='font-family:"Times New Roman"'>&nbsp;</span></p>
</div>
</body>
</html>