进程的同步.docx

上传人:b****1 文档编号:13419426 上传时间:2023-06-14 格式:DOCX 页数:14 大小:163.48KB
下载 相关 举报
进程的同步.docx_第1页
第1页 / 共14页
进程的同步.docx_第2页
第2页 / 共14页
进程的同步.docx_第3页
第3页 / 共14页
进程的同步.docx_第4页
第4页 / 共14页
进程的同步.docx_第5页
第5页 / 共14页
进程的同步.docx_第6页
第6页 / 共14页
进程的同步.docx_第7页
第7页 / 共14页
进程的同步.docx_第8页
第8页 / 共14页
进程的同步.docx_第9页
第9页 / 共14页
进程的同步.docx_第10页
第10页 / 共14页
进程的同步.docx_第11页
第11页 / 共14页
进程的同步.docx_第12页
第12页 / 共14页
进程的同步.docx_第13页
第13页 / 共14页
进程的同步.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

进程的同步.docx

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

进程的同步.docx

进程的同步

操作系统

实验报告

课程名称

操作系统实验

实验项目名称

进程的同步

学号

2009142212

班级

20100614

姓名

刘欣卓

专业

计算机科学与技术

学生所在学院

计算机科学

与技术学院

指导教师

初妍

实验室名称地点

21#428

 

哈尔滨工程大学

计算机科学与技术学院

一、实验概述

1.实验名称

第三讲进程的同步

2.实验目的

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

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

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

3.实验类型

验证性实验、设计性试验

4.实验内容

(1)准备实验

启动OSLab。

新建一个EOSKernel项目。

生成EOSKernel项目,从而在该项目文件夹中生成SDK文件夹。

新建一个EOS应用程序项目。

使用在第3步生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。

(2)生产者-消费者同步执行的过程

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

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

按F5启动调试。

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

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

立即激活虚拟机窗口查看生产者-消费者同步执行的过程。

待应用程序执行完毕后,结束此次调试。

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

I创建信号量

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

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

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

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

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

按F11调试进入CreateSemaphore函数。

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

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

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

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

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

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

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

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

II等待、释放信号量

1、等待信号量(不阻塞)

删除所有的断点。

在eosapp.c文件的Producer函数中,等待Empty信号量的代码行(第144行)WaitForSingleObject(EmptySemaphoreHandle,INFINITE);添加一个断点。

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

WaitForSingleObject函数最终会调用内核中的PsWaitForSemaphore函数完成等待操作。

所以,在semaphore.c文件中PsWaitForSemaphore函数的第一行(第68行)添加一个断点。

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

按F10单步调试,直到完成PsWaitForSemaphore函数中的所有操作。

2、释放信号量(不唤醒)

删除所有的断点。

在eosapp.c文件的Producer函数中,释放Full信号量的代码行(第152行)ReleaseSemaphore(FullSemaphoreHandle,1,NULL);添加一个断点。

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

按F11调试进入ReleaseSemaphore函数。

继续按F11调试进入PsReleaseSemaphoreObject函数。

先使用F10单步调试,当黄色箭头指向第269行时使用F11单步调试,进入PsReleaseSemaphore函数。

按F10单步调试,直到完成PsReleaseSemaphore函数中的所有操作。

3、等待信号量(阻塞)

结束之前的调试。

删除所有的断点。

按F5重新启动调试。

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

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

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

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

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

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

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

在“调用堆栈”窗口中双击PsWaitForSemaphore函数的堆栈帧,查看Empty信号量计数(Semaphore->Count)的值为-1,所以会调用PspWait函数将生产者线程放入Empty信号量的等待队列中进行等待(让出CPU)。

激活虚拟机窗口查看输出的结果。

生产了从0到13的14个产品,但是只消费了从0到3的4个产品,所以缓冲池中的10个缓冲区就都被占用了,这与之前调试的结果是一致的。

4、释放信号量(唤醒)

删除所有断点。

在eosapp.c文件的Consumer函数中,释放Empty信号量的代码行(第180行)ReleaseSemaphore(EmptySemaphoreHandle,1,NULL);添加一个断点。

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

查看Consumer函数中变量i的值为4,说明已经消费了4号产品。

按照释放信号量(不唤醒)中的方法使用F10和F11调试进入PsReleaseSemaphore函数。

查看PsReleaseSemaphore函数中Empty信号量计数(Semaphore->Count)的值为-1,和生产者线程被阻塞时的值是一致的。

按F10单步调试PsReleaseSemaphore函数,直到在代码行(第132行)PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS);处中断。

此时Empty信号量计数的值已经由-1增加为了0,需要调用PspWakeThread函数唤醒阻塞在Empty信号量等待队列中的生产者线程(放入就绪队列中),然后调用PspSchedule函数执行调度,这样生产者线程就得以继续执行。

III验证生产者线程被唤醒后从被阻塞时的状态继续执行

在semaphore.c文件中PsWaitForSemaphore函数的最后一行(第83行)代码处添加一个断点。

按F5继续调试,在断点处中断。

查看PsWaitForSemaphore函数中Empty信号量计数(Semaphore->Count)的值为0,和生产者线程被唤醒时的值是一致的。

在“调用堆栈”窗口中可以看到是由Producer函数进入的。

激活Producer函数的堆栈帧,查看Producer函数中变量i的值为14,表明之前被阻塞的、正在尝试生产14号产品的生产者线程已经从PspWait函数返回并继续执行了。

结束此次调试。

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

修改PsWaitForSemaphore函数

先用计数值和0比较,当计数值大于0时,将计数值减1后直接返回成功;当计数值等于0时,调用PspWait函数阻塞线程的执行(将参数Milliseconds做为PspWait函数的第二个参数,并使用PspWait函数的返回值做为返回值)。

在函数开始定义一个STATUS类型的变量,用来保存不同情况下的返回值,并在函数最后返回此变量的值。

绝不能在原子操作的中途返回!

修改PsReleaseSemaphore函数

如果被阻塞的线程数量大于等于ReleaseCount,则循环结束后,有ReleaseCount个线程会被唤醒,而且信号量计数的值仍然为0;如果被阻塞的线程数量(可以为0)小于ReleaseCount,则循环结束后,所有被阻塞的线程都会被唤醒,并且信号量的计数值=ReleaseCount-之前被阻塞线程的数量+之前信号量的计数值。

(5)测试方法

使用修改完毕的EOSKernel项目生成完全版本的SDK文件夹,并覆盖之前的生产者-消费者应用程序项目的SDK文件夹。

按F5调试执行原有的生产者-消费者应用程序项目,结果必须仍然与图13-2一致。

如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,将Producer函数中等待Empty信号量的代码行

WaitForSingleObject(EmptySemaphoreHandle,INFINITE);

替换为

while(WAIT_TIMEOUT==WaitForSingleObject(EmptySemaphoreHandle,300)){

printf("Producerwaitforemptysemaphoretimeout\n");}

将Consumer函数中等待Full信号量的代码行

WaitForSingleObject(FullSemaphoreHandle,INFINITE);

替换为while(WAIT_TIMEOUT==WaitForSingleObject(FullSemaphoreHandle,300)){

printf("Consumerwaitforfullsemaphoretimeout\n");}启动调试新的生产者-消费者项目,查看在虚拟机中输出的结果,验证信号量超时等待功能是否能够正常执行。

如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改。

如果超时等待功能已经能够正常执行,可以考虑将消费者线程修改为一次消费两个产品,来测试ReleaseCount参数是否能够正常使用。

使用实验文件夹中NewConsumer.c文件中的Consumer函数替换原有的Consumer函数。

二、实验环境

TevationOSLab1.0.3.9900

3、实验过程

一、设计思路:

1启动OSLab

3.1准备实验

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

3.3调试EOS信号量的工作过程

3.3.1创建信号量

3.3.2等待、释放信号量

3.3.2.1等待信号量(不阻塞)

3.3.2.2释放信号量(不唤醒)

3.3.2.3等待信号量(阻塞)

3.3.2.4释放信号量(唤醒)

3.4修改EOS的信号量算法

3.4.1要求

3.4.2提示

3.4.3测试方法

3.5退出系统并保存oud文件

2、算法设计:

本次实验要求修改信号量算法

1、修改PsWaitForSemaphore函数

PsWaitForSemaphore函数中原有的代码段

Semaphore->Count--;

if(Semaphore->Count<0)

{PspWait(&Semaphore->WaitListHead,INFINITE);}

应被修改为:

先用计数值和0比较,当计数值大于0时,将计数值减1后直接返回成功;当计数值等于0时,调用PspWait函数阻塞线程的执行(将参数Milliseconds做为PspWait函数的第二个参数,并使用PspWait函数的返回值做为返回值)。

在函数开始定义一个STATUS类型的变量,用来保存不同情况下的返回值,并在函数最返回此变量的值。

绝不能在原子操作的中途返回!

在EOSKernel项目ps/sched.c文件的第190行查看PspWait函数的说明和源代码。

按要求应修改为:

if(Semaphore->Count>0)

{

Semaphore->Count--;

flag=STATUS_SUCCESS;

}//信号量大于0,说明可以为线程分配资源

else

{

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

//信号量小于0,需要等待

}

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

returnflag;

2、修改PsReleaseSemaphore函数

编写一个使用ReleaseCount做为计数器的循环体,来替换PsReleaseSemaphore函数中原有的代码段

Semaphore->Count++;

if(Semaphore->Count<=0)

{

PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS);

}

在循环体中完成下面的工作:

1.如果被阻塞的线程数量大于等于ReleaseCount,则循环结束后,有ReleaseCount个线程会被唤醒,而且信号量计数的值仍然为0;

2.如果被阻塞的线程数量(可以为0)小于ReleaseCount,则循环结束后,所有被阻塞的线程都会被唤醒,并且信号量的计数值=ReleaseCount-之前被阻塞线程的数量+之前信号量的计数值。

在EOSKernel项目ps/sched.c文件的第294行查看PspWakeThread函数的说明和源代码。

在循环的过程中可以使用宏定义函数ListIsEmpty判断信号量的等待队列是否为空,例如ListIsEmpty(&Semaphore->WaitListHead)可以在EOSKernel项目inc/rtl.h文件的第113行查看此宏定义的源代码。

按要求应修改为:

while((!

ListIsEmpty(&Semaphore->WaitListHead))&&(ReleaseCount))

{

PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS);

PspThreadSchedule();

ReleaseCount--;

}

Semaphore->Count=Semaphore->Count+ReleaseCount;

//可能有线程被唤醒,执行线程调度。

Status=STATUS_SUCCESS;

}

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

returnStatus;

3、测试方法

修改完毕后,可以按照下面的方法进行测试:

1.使用修改完毕的EOSKernel项目生成完全版本的SDK文件夹,并覆盖之前的生产者-消费者应用程序项目的SDK文件夹。

2.按F5调试执行原有的生产者-消费者应用程序项目,结果必须仍然与图13-2一致。

如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,并重复步骤1。

3.将Producer函数中等待Empty信号量的代码行WaitForSingleObject(EmptySemaphoreHandle,INFINITE);

替换为

while(WAIT_TIMEOUT==WaitForSingleObject(EmptySemaphoreHandle,300))

{printf("Producerwaitforemptysemaphoretimeout\n");}

将Consumer函数中等待Full信号量的代码行WaitForSingleObject(FullSemaphoreHandle,INFINITE);

替换为

while(WAIT_TIMEOUT==WaitForSingleObject(FullSemaphoreHandle,300))

{printf("Consumerwaitforfullsemaphoretimeout\n");}

启动调试新的生产者-消费者项目,查看在虚拟机中输出的结果,验证信号量超时等待功能是否能够正常执行。

如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,并重复步骤1。

如果超时等待功能已经能够正常执行,可以考虑将消费者线程修改为一次消费两个产品,来测试ReleaseCount参数是否能够正常使用。

使用实验文件夹中NewConsumer.c文件中的Consumer函数替换原有的Consumer函数。

3、实验要求:

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

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

因为缓冲池已满,此时生成了14个产品(0~13),只消费了4个(0~3),缓冲池大小为10,因此生产者必须等消费者消费了4号产品后,再生产14号产品。

简单地说,在同一地址空间执行2个线程:

生产者线程和消费者线程。

生产者线程生产产品,放入缓冲池等待消费者消费,消费者线程从缓冲池中获得产品,释放缓冲池。

当生产者线程生产物品时,如果缓冲池已满,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

2、P145-3.4修改EOS的信号量算法(只看一次消费1个产品的,一次消费2个产品的可以写到实验报告中)

修改方法请参考本实验报告算法部分。

下面给出运行截图:

修改前:

修改后:

 

3、P147-四、思考与练习-2.绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。

 

PsWaitForSemaphore:

 

PsReleaseSemaphore:

 

 

四、实验心得

1、了解了EOS在PC机上进程创的过程。

2、查看EOS进程创建的状态和行为,理解进程同步的具体执行方法。

3、对创建进程的函数进行了修改,使得可以查看缓冲池是否满。

 

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

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

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

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