操作系统实验四 进程的同步.docx

上传人:b****1 文档编号:13403356 上传时间:2023-06-13 格式:DOCX 页数:27 大小:496.69KB
下载 相关 举报
操作系统实验四 进程的同步.docx_第1页
第1页 / 共27页
操作系统实验四 进程的同步.docx_第2页
第2页 / 共27页
操作系统实验四 进程的同步.docx_第3页
第3页 / 共27页
操作系统实验四 进程的同步.docx_第4页
第4页 / 共27页
操作系统实验四 进程的同步.docx_第5页
第5页 / 共27页
操作系统实验四 进程的同步.docx_第6页
第6页 / 共27页
操作系统实验四 进程的同步.docx_第7页
第7页 / 共27页
操作系统实验四 进程的同步.docx_第8页
第8页 / 共27页
操作系统实验四 进程的同步.docx_第9页
第9页 / 共27页
操作系统实验四 进程的同步.docx_第10页
第10页 / 共27页
操作系统实验四 进程的同步.docx_第11页
第11页 / 共27页
操作系统实验四 进程的同步.docx_第12页
第12页 / 共27页
操作系统实验四 进程的同步.docx_第13页
第13页 / 共27页
操作系统实验四 进程的同步.docx_第14页
第14页 / 共27页
操作系统实验四 进程的同步.docx_第15页
第15页 / 共27页
操作系统实验四 进程的同步.docx_第16页
第16页 / 共27页
操作系统实验四 进程的同步.docx_第17页
第17页 / 共27页
操作系统实验四 进程的同步.docx_第18页
第18页 / 共27页
操作系统实验四 进程的同步.docx_第19页
第19页 / 共27页
操作系统实验四 进程的同步.docx_第20页
第20页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

操作系统实验四 进程的同步.docx

《操作系统实验四 进程的同步.docx》由会员分享,可在线阅读,更多相关《操作系统实验四 进程的同步.docx(27页珍藏版)》请在冰点文库上搜索。

操作系统实验四 进程的同步.docx

操作系统实验四进程的同步

操作系统

实验报告

课程名称

操作系统实验

课程编号

0920311

实验项目名称

操作系统的启动

学号

年级

2011级

姓名

专业

软件工程

学生所在学院

软件学院

指导教师

王红滨

实验室名称地点

软件工程实验室21B282

哈尔滨工程大学

软件学院

第六讲进程的同步

一、实验概述

1.实验名称

实验系统的启动

2.实验目的

1).使用EOS的信号量编程解决生产者—消费者问题,理解进程同步的意义。

2).调试跟踪EOS的信号量的工作过程,理解进程同步的原理。

3).修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。

3.实验类型(验证、设计)

验证

4.实验内容

1).准备实验

2).使用EOS的信号量解决生产者-消费者问题

3).调试EOS信号量的工作过程

①创建信号量

②等待释放信号量

③等待信号量(不阻塞)

④释放信号量(不唤醒)

⑤等待信号量(阻塞)

⑥释放信号量(唤醒)

4).修改EOS的信号量算法

在目前EOSKernel项目的ps/semaphore.c文件中,PsWaitForSemaphore函数的Milliseconds参数只能是INFINITE,PsReleaseSemaphore函数的ReleaseCount参数只能是1。

现在要求同时修改PsWaitForSemaphore函数和PsReleaseSemaphore函数中的代码,使这两个参数能够真正起到作用,使信号量对象支持等待超时唤醒功能和批量释放功能。

二、实验环境

操作系统:

windowsxp

编译环境:

OSLab

三、实验过程

1.设计思路和流程图

图3-1.整体试验流程图

图3-2.Main函数流程图、生产者消费、消费者流程图

 

2.需要解决的问题及解答

(1).思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?

答:

在执行等待信号量和释放信号量的时候,是不允许cpu响应外部中断的,如果此时cpu响应了外部中断,会产生不可预料的结果,无法正常完成原子操作。

(2).绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。

1).PsWaitForSemaphore函数流程图。

 

2).PsReleaseSemaphore函数流程图

 

 

 

 

 

(3).P143生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢?

生产者和消费者是怎样使用同步对象来实现该同步过程的呢?

答:

这是因为临界资源的限制。

缓冲区只有十个空间,现在消费比生产慢,此时分别装了4到13号产品,而消费者只消费了3个。

此时装入产品与产品的存储空间成为直接相互制约关系,再消费者消费了下一个产品之前生产者不能继续装入。

因此,可解释生产者为什么必须等待消费者消费了4号产品后才能生产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号产品时才会在该条件断点处中断。

3.主要数据结构、实现代码及其说明

1).对PsWaitForSemaphore函数的修改:

PsWaitForSemaphore(

INPSEMAPHORESemaphore,

INULONGMilliseconds

/*++

功能描述:

信号量的Wait操作(P操作)。

参数:

Semaphore--Wait操作的信号量对象。

Milliseconds--等待超时上限,单位毫秒。

返回值:

STATUS_SUCCESS。

当你修改信号量使之支持超时唤醒功能后,如果等待超时,应该返回STATUS_TIMEOUT。

--*/

{

BOOLIntState;

STATUSa;

ASSERT(KeGetIntNesting()==0);//中断环境下不能调用此函数。

IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。

//

//目前仅实现了标准记录型信号量,不支持超时唤醒功能,所以PspWait函数

//的第二个参数的值只能是INFINITE。

//

if(Semaphore->Count>0){

Semaphore->Count--;

a=STATUS_SUCCESS;

}

elseif(Semaphore->Count==0)

a=PspWait(&Semaphore->WaitListHead,Milliseconds);

KeEnableInterrupts(IntState);//原子操作完成,恢复中断。

returna;

}

对PsReleaseSemaphore函数的修改:

PsReleaseSemaphore(

INPSEMAPHORESemaphore,

INLONGReleaseCount,

OUTPLONGPreviousCount

/*++

功能描述:

信号量的Signal操作(V操作)。

参数:

Semaphore--Wait操作的信号量对象。

ReleaseCount--信号量计数增加的数量。

当前只能为1。

当你修改信号量使之支持

超时唤醒功能后,此参数的值能够大于等于1。

PreviousCount--返回信号量计数在增加之前的值。

返回值:

如果成功释放信号量,返回STATUS_SUCCESS。

--*/

{

STATUSStatus;

BOOLIntState;

//intbobo;

IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。

if(Semaphore->Count+ReleaseCount>Semaphore->MaximumCount){

Status=STATUS_SEMAPHORE_LIMIT_EXCEEDED;

}else{

//

//记录当前的信号量的值。

//

if(NULL!

=PreviousCount){

*PreviousCount=Semaphore->Count;

}

//

//目前仅实现了标准记录型信号量,每执行一次信号量的释放操作

//只能使信号量的值增加1。

//

if(ReleaseCount<0)

return0;

for(;ReleaseCount>0&&!

(ListIsEmpty(&Semaphore->WaitListHead));ReleaseCount-=1){

PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS);

}

Semaphore->Count+=ReleaseCount;

Status=STATUS_SUCCESS;

}

KeEnableInterrupts(IntState);//原子操作完成,恢复中断。

returnStatus;

}

4.源程序并附上注释

#include"psp.h"

VOID

PsInitializeSemaphore(

INPSEMAPHORESemaphore,

INLONGInitialCount,

INLONGMaximumCount

/*++

功能描述:

初始化信号量结构体。

参数:

Semaphore--要初始化的信号量结构体指针。

InitialCount--信号量的初始值,不能小于0且不能大于MaximumCount。

MaximumCount--信号量的最大值,必须大于0。

返回值:

无。

--*/

{

ASSERT(InitialCount>=0&&InitialCount<=MaximumCount&&MaximumCount>0);

Semaphore->Count=InitialCount;

Semaphore->MaximumCount=MaximumCount;

ListInitializeHead(&Semaphore->WaitListHead);

}

STATUS

PsWaitForSemaphore(

INPSEMAPHORESemaphore,

INULONGMilliseconds

/*++

功能描述:

信号量的Wait操作(P操作)。

参数:

Semaphore--Wait操作的信号量对象。

Milliseconds--等待超时上限,单位毫秒。

返回值:

STATUS_SUCCESS。

当你修改信号量使之支持超时唤醒功能后,如果等待超时,应该返回STATUS_TIMEOUT。

--*/

{

BOOLIntState;

STATUSa;

ASSERT(KeGetIntNesting()==0);//中断环境下不能调用此函数。

IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。

//

//目前仅实现了标准记录型信号量,不支持超时唤醒功能,所以PspWait函数

//的第二个参数的值只能是INFINITE。

//

if(Semaphore->Count>0){

Semaphore->Count--;

a=STATUS_SUCCESS;

}

elseif(Semaphore->Count==0)

a=PspWait(&Semaphore->WaitListHead,Milliseconds);

KeEnableInterrupts(IntState);//原子操作完成,恢复中断。

returna;

}

STATUS

PsReleaseSemaphore(

INPSEMAPHORESemaphore,

INLONGReleaseCount,

OUTPLONGPreviousCount

/*++

功能描述:

信号量的Signal操作(V操作)。

参数:

Semaphore--Wait操作的信号量对象。

ReleaseCount--信号量计数增加的数量。

当前只能为1。

当你修改信号量使之支持

超时唤醒功能后,此参数的值能够大于等于1。

PreviousCount--返回信号量计数在增加之前的值。

返回值:

如果成功释放信号量,返回STATUS_SUCCESS。

--*/

{

STATUSStatus;

BOOLIntState;

IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。

if(Semaphore->Count+ReleaseCount>Semaphore->MaximumCount){

Status=STATUS_SEMAPHORE_LIMIT_EXCEEDED;

}else{

//

//记录当前的信号量的值。

//

if(NULL!

=PreviousCount){

*PreviousCount=Semaphore->Count;

}

//

//目前仅实现了标准记录型信号量,每执行一次信号量的释放操作

//只能使信号量的值增加1。

//

if(ReleaseCount<0)

return0;

for(;ReleaseCount>0&&!

(ListIsEmpty(&Semaphore->WaitListHead));ReleaseCount-=1){

PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS);

}

Semaphore->Count+=ReleaseCount;

Status=STATUS_SUCCESS;

}

KeEnableInterrupts(IntState);//原子操作完成,恢复中断。

returnStatus;

}

//////////////////////////////////////////////////////////////////////////

//

//下面是和信号量对象类型相关的代码。

//

//

//信号量对象类型指针。

//

POBJECT_TYPEPspSemaphoreType=NULL;

//

//用于初始化semaphore结构体的参数结构体。

//

typedefstruct_SEM_CREATE_PARAM{

LONGInitialCount;

LONGMaximumCount;

}SEM_CREATE_PARAM,*PSEM_CREATE_PARAM;

//

//semaphore对象的构造函数,在创建新semaphore对象时被调用。

//

VOID

PspOnCreateSemaphoreObject(

INPVOIDSemaphoreObject,

INULONG_PTRCreateParam

{

PsInitializeSemaphore((PSEMAPHORE)SemaphoreObject,

((PSEM_CREATE_PARAM)CreateParam)->InitialCount,

((PSEM_CREATE_PARAM)CreateParam)->MaximumCount);

}

//

//semaphore对象类型的初始化函数。

//

VOID

PspCreateSemaphoreObjectType(

VOID

{

STATUSStatus;

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对象的构造函数。

//

STATUS

PsCreateSemaphoreObject(

INLONGInitialCount,

INLONGMaximumCount,

INPSTRName,

OUTPHANDLESemaphoreHandle

{

STATUSStatus;

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);

if(!

EOS_SUCCESS(Status)){

returnStatus;

}

Status=ObCreateHandle(SemaphoreObject,SemaphoreHandle);

if(!

EOS_SUCCESS(Status)){

ObDerefObject(SemaphoreObject);

}

returnStatus;

}

//

//semaphore对象的signal操作函数。

//

STATUS

PsReleaseSemaphoreObject(

INHANDLEHandle,

INLONGReleaseCount,

INPLONGPreviousCount

{

STATUSStatus;

PSEMAPHORESemaphore;

if(ReleaseCount<1){

returnSTATUS_INVALID_PARAMETER;

}

//由semaphore句柄得到semaphore对象的指针。

Status=ObRefObjectByHandle(Handle,PspSemaphoreType,(PVOID*)&Semaphore);

if(EOS_SUCCESS(Status)){

Status=PsReleaseSemaphore(Semaphore,ReleaseCount,PreviousCount);

ObDerefObject(Semaphore);

}

returnStatus;

}

5.程序运行时的初值和运行结果

a.使用EOS的信号量解决生产者-消费者问题

1).使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码

2).按F7生成修改后的EOS应用程序项目。

3).按F5启动调试。

OSLab会首先弹出一个调试异常对话框。

4).在调试异常对话框中选择“否”,继续执行。

5).立即激活虚拟机窗口查看生产者-消费者同步执行的过程,如下图。

b.创建信号量

1).按F5启动调试EOS应用项目。

OSLab会首先弹出一个调试异常对话框。

2).在调试异常对话框中选择“是”,调试会中断。

3).在main函数中创建Empty信号量的代码行(第77行EmptySemaphoreHandle=CreateSemaphore(BUFFER_SIZE,BUFFER_SIZE,NULL);添加一个断点。

4).按F5继续调试,到此断点处中断。

5).按F11调试进入CreateSemaphore函数。

可以看到此API函数只是调用了EOS内核中的PsCreateSemaphoreObject函数来创建信号量对象。

6).按F11调试进入semaphore.c文件中的PsCreateSemaphoreObject函数。

在此函数中,会在EOS内核管理的内存中创建一个信号量对象(分配一块内存),而初始化信号量对象中各个成员的操作是在PsInitializeSemaphore函数中完成的。

7).在semaphore.c文件的顶部查找到PsInitializeSemaphore函数的定义(第19行),在此函数的第一行(第39行)代码处添加一个断点。

8).按F5继续调试,到断点处中断。

观察PsInitializeSemaphore函数中用来初始化信号量结构体成员的值,应该和传入CreateSemaphore函数的参数值是一致的。

9).按F10单步调试PsInitializeSemaphore函数执行的过程,查看信号量结构体被初始化的过程。

打开“调用堆栈”窗口,查看函数的调用层次。

c.等待、释放信号量

1).结束之前的调试。

2).删除所有的断点。

3).按F5重新启动调试。

OSLab会首先弹出一个调试异常对话框。

4).在调试异常对话框中选择“是”,调试会中断。

5).在semaphore.c文件中的PsWaitForSemaphore函数的PspWait(&Semaphore->WaitListHead,INFINITE);代码行(第78行)添加一个断点。

6).按F5继续调试,并立即激活虚拟机窗口查看输出。

开始时生产者、消费者都不会被信号量阻塞,同步执行一段时间后才在断点处中断。

7).中断后,查看“调用堆栈”窗口,有Producer函数对应的堆栈帧,说明此次调用是从生产者线程函数进入的。

8).在“调用堆栈”窗口中双击Producer函数所在的堆栈帧,绿色箭头指向等待Empty信号量的代码行,查看Producer函数中变量i的值为14,表示生产者线程正在尝试生产14号产品。

9).在“调用堆栈”窗口中双击PsWaitForSemaphore函数的堆栈帧,查看Empty信号量计数(Semaphore->Count

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2