进程的同步实验报告Word下载.docx
- 文档编号:18106803
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:15
- 大小:166.12KB
进程的同步实验报告Word下载.docx
《进程的同步实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《进程的同步实验报告Word下载.docx(15页珍藏版)》请在冰豆网上搜索。
4.实验内容
⑴准备实验
⑵使用EOS的信号量解决生产者-消费者问题
⑶调试EOS信号量的工作过程
①创建信号量
②等待释放信号量
③等待信号量(不阻塞)
④释放信号量(不唤醒)
⑤等待信号量(阻塞)
⑥释放信号量(唤醒)
⑷修改EOS的信号量算法
二、实验环境
WindowsXP+EOS集成实验环境
三、实验过程
1.设计思路和流程图
图4-1.整体试验流程图
main函数开始
创建Mutex对象
创建Empty信号量对象
创建Full信
号量对象
创建生产者线程
创建消费者线程
等待生产者线程和消费者线程结束
关闭句柄
main函数结束
Producer函数开始
生产完毕?
等待Empty信号量对象
等待Mutex对象
生产一个产品,占用一个缓冲区
循环向后移动缓冲区指针
释放Mutex对象
释放Full信号量对象
等待500毫秒
Producer函数结束
是
否
Consumer函数开始
消费完毕毕?
等待Full信号量对象
消费一个产品,清空一个缓冲区
释放Empty信号量对象
前10个产品?
等待2000毫秒
等待100毫秒
Consumer函数结束
图4-2.Main函数流程图、生产者消费、消费者流程图
2.算法实现
3.需要解决的问题及解答
(1).思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?
答:
在执行等待信号量和释放信号量的时候,是不允许cpu响应外部中断的,如果此时cpu响应了外部中断,会产生不可预料的结果,无法正常完成原子操作。
(2).绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。
(3).P143生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢?
生产者和消费者是怎样使用同步对象来实现该同步过程的呢?
这是因为临界资源的限制。
临界资源就像产品仓库,只有“产品仓库”空闲生产者才能生产东西,有权向里面放东西。
所以它必须等到消费者,取走产品,“产品空间”(临界资源)空闲时,才继续生产14号产品。
(4).根据本实验3.3.2节中设置断点和调试的方法,自己设计一个类似的调试方案来验证消费者线程在消费24号产品时会被阻塞,直到生产者线程生产了24号产品后,消费者线程才被唤醒并继续执行的过程。
可以按照下面的步骤进行调试
(1)删除所有的断点。
(2)按F5启动调试。
OSLab会首先弹出一个调试异常对话框。
(3)在调试异常对话框中选择“是”,调试会中断。
(4)在Consumer函数中等待Full信号量的代码行(第173行)WaitForSingleObject(FullSemaphoreHandle,INFINITE);
添加一个断点。
(5)在“断点”窗口(按Alt+F9打开)中此断点的名称上点击右键。
(6)在弹出的快捷菜单中选择“条件”。
(7)在“断点条件”对话框(按F1获得帮助)的表达式编辑框中,输入表达式“i==24”。
(8)点击“断点条件”对话框中的“确定”按钮。
(9)按F5继续调试。
只有当消费者线程尝试消费24号产品时才会在该条件断点处中断。
4.主要数据结构、实现代码及其说明
修改PsWaitForSemaphore函数
if(Semaphore->
Count>
0){
Semaphore->
Count--;
flag=STATUS_SUCCESS;
}//如果信号量大于零,说明尚有资源,可以为线程分配
else
flag=PspWait(&
Semaphore->
WaitListHead,Milliseconds);
KeEnableInterrupts(IntState);
//原子操作完成,恢复中断。
returnflag;
}//否则,说明资源数量不够,不能再为线程分配资源,因此要使线程等待
修改PsReleaseSemaphore函数
Count+ReleaseCount>
Semaphore->
MaximumCount){
Status=STATUS_SEMAPHORE_LIMIT_EXCEEDED;
}else{
//记录当前的信号量的值。
if(NULL!
=PreviousCount){
*PreviousCount=Semaphore->
Count;
}
intmm=Semaphore->
//目前仅实现了标准记录型信号量,每执行一次信号量的释放操作
//只能使信号量的值增加1。
while((!
ListIsEmpty(&
WaitListHead))&
&
(ReleaseCount)){
PspWakeThread(&
WaitListHead,STATUS_SUCCESS);
PspThreadSchedule();
ReleaseCount--;
Count=mm+ReleaseCount;
//可能有线程被唤醒,执行线程调度。
Status=STATUS_SUCCESS;
}
5.源程序并附上注释
#include"
psp.h"
VOID
PsInitializeSemaphore(
INPSEMAPHORESemaphore,
INLONGInitialCount,
INLONGMaximumCount)
/*++
功能描述:
初始化信号量结构体。
参数:
Semaphore--要初始化的信号量结构体指针。
InitialCount--信号量的初始值,不能小于0且不能大于MaximumCount。
MaximumCount--信号量的最大值,必须大于0。
返回值:
无。
--*/
{
ASSERT(InitialCount>
=0&
InitialCount<
=MaximumCount&
MaximumCount>
0);
Count=InitialCount;
MaximumCount=MaximumCount;
ListInitializeHead(&
WaitListHead);
}
STATUS
PsWaitForSemaphore(
INULONGMilliseconds)
信号量的Wait操作(P操作)。
Semaphore--Wait操作的信号量对象。
Milliseconds--等待超时上限,单位毫秒。
STATUS_SUCCESS。
当你修改信号量使之支持超时唤醒功能后,如果等待超时,应该返回STATUS_TIMEOUT。
BOOLIntState;
STATUSflag;
ASSERT(KeGetIntNesting()==0);
//中断环境下不能调用此函数。
IntState=KeEnableInterrupts(FALSE);
//开始原子操作,禁止中断。
//目前仅实现了标准记录型信号量,不支持超时唤醒功能,所以PspWait函数
//的第二个参数的值只能是INFINITE。
if(Semaphore->
PsReleaseSemaphore(
INLONGReleaseCount,
OUTPLONGPreviousCount
)
信号量的Signal操作(V操作)。
ReleaseCount--信号量计数增加的数量。
当前只能为1。
当你修改信号量使之支持
超时唤醒功能后,此参数的值能够大于等于1。
PreviousCount--返回信号量计数在增加之前的值。
如果成功释放信号量,返回STATUS_SUCCESS。
STATUSStatus;
returnStatus;
//////////////////////////////////////////////////////////////////////////
//下面是和信号量对象类型相关的代码。
//信号量对象类型指针。
POBJECT_TYPEPspSemaphoreType=NULL;
//用于初始化semaphore结构体的参数结构体。
typedefstruct_SEM_CREATE_PARAM{
LONGInitialCount;
LONGMaximumCount;
}SEM_CREATE_PARAM,*PSEM_CREATE_PARAM;
//semaphore对象的构造函数,在创建新semaphore对象时被调用。
PspOnCreateSemaphoreObject(
INPVOIDSemaphoreObject,
INULONG_PTRCreateParam)
PsInitializeSemaphore((PSEMAPHORE)SemaphoreObject,
((PSEM_CREATE_PARAM)CreateParam)->
InitialCount,
MaximumCount);
//semaphore对象类型的初始化函数。
PspCreateSemaphoreObjectType(
VOID)
OBJECT_TYPE_INITIALIZERInitializer;
Initializer.Create=PspOnCreateSemaphoreObject;
Initializer.Delete=NULL;
Initializer.Wait=(OB_WAIT_METHOD)PsWaitForSemaphore;
Initializer.Read=NULL;
Initializer.Write=NULL;
Status=ObCreateObjectType("
SEMAPHORE"
&
Initializer,&
PspSemaphoreType);
if(!
EOS_SUCCESS(Status)){
KeBugCheck("
Failedtocreatesemaphoreobjecttype!
"
);
//semaphore对象的构造函数。
PsCreateSemaphoreObject(
INLONGMaximumCount,
INPSTRName,
OUTPHANDLESemaphoreHandle
PVOIDSemaphoreObject;
SEM_CREATE_PARAMCreateParam;
if(InitialCount<
0||MaximumCount<
=0||InitialCount>
MaximumCount){
returnSTATUS_INVALID_PARAMETER;
//创建信号量对象。
CreateParam.InitialCount=InitialCount;
CreateParam.MaximumCount=MaximumCount;
Status=ObCreateObject(PspSemaphoreType,
Name,
sizeof(SEMAPHORE),
(ULONG_PTR)&
CreateParam,
&
SemaphoreObject);
returnStatus;
Status=ObCreateHandle(SemaphoreObject,SemaphoreHandle);
ObDerefObject(SemaphoreObject);
returnStatus;
//semaphore对象的signal操作函数。
PsReleaseSemaphoreObject(
INHANDLEHandle,
INPLONGPreviousCount)
PSEMAPHORESemaphore;
if(ReleaseCount<
1){
//由semaphore句柄得到semaphore对象的指针。
Status=ObRefObjectByHandle(Handle,PspSemaphoreType,(PVOID*)&
Semaphore);
if(EOS_SUCCESS(Status)){
Status=PsReleaseSemaphore(Semaphore,ReleaseCount,PreviousCount);
ObDerefObject(Semaphore);
6.程序运行时的初值和运行结果
四、实验体会
经过本次实验,初步了解操作系统的进程同步的过程。
我对生产者-消费者问题的解决办法有了更全面的认识,同时对调试代码更加熟练。
本次实验最大的体会就是,做东西要细心,在写代码的过程中,稍不留意就给后期调试工作带来很多问题。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 进程 同步 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)