第六讲 进程的同步.docx
- 文档编号:29846369
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:15
- 大小:307.77KB
第六讲 进程的同步.docx
《第六讲 进程的同步.docx》由会员分享,可在线阅读,更多相关《第六讲 进程的同步.docx(15页珍藏版)》请在冰豆网上搜索。
第六讲进程的同步
操作系统
实验报告
课程名称
操作系统实验
课程编号
0906553
实验项目名称
进程的同步
学号
班级
姓名
专业
计算机科学与技术
学生所在学院
计算机科学与技术学院
指导教师
王红滨
实验室名称地点
21B475
哈尔滨工程大学
计算机科学与技术学院
一、实验概述
1.实验名称
进程的同步
2.实验目的
1)使用EOS的信号量,编程解决生产者—消费者问题,理解进程同步的意义。
2)调试跟踪EOS信号量的工作过程,理解进程同步的原理。
3)修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。
3.实验类型
验证+设计
4.实验内容
1)准备实验
2)使用EOS的信号量解决生产者-消费者问题
3)调试EOS信号量的工作过程
a)创建信号量
b)等待、释放信号量
i.等待信号量(不阻塞)
ii.释放信号量(不唤醒)
iii.等待信号量(阻塞)
iv.释放信号量(唤醒)
4)修改EOS的信号量算法
二、实验环境
操作系统:
Windows操作系统
编译器:
集成开发环境OSLab
工具:
FloppyImageEditor工具
语言:
C语言
三、实验过程
1.设计思路和流程图
图1实验过程
图2main函数执行过程
图3生产者-消费者进程
2.需要解决的问题及解答
1)P143,生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢?
生产者和消费者是怎样使用同步对象来实现该同步过程的呢?
答:
因为当生产者生产13号产品后,消费者只消费了3个产品,此时信号量EmptySemaphoreHandle的计数为0,生产者必须等待消费者继续消费产品,释放信号量EmptySemaphoreHandle,生产者才能继续执行。
2)绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。
图4PsWaitForSemaphore流程图
图5PsReleaseSemaphore函数流程图
3.源程序并附上注释
1)修改PsWaitForSemaphore函数
STATUSPsWaitForSemaphore(INPSEMAPHORESemaphore,
INULONGMilliseconds)
{
BOOLIntState;
STATUSStatus;
ASSERT(KeGetIntNesting()==0);//中断环境下不能调用此函数。
IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。
if(Semaphore->Count>0){
Semaphore->Count--;
Status=STATUS_SUCCESS;
}elseif(Semaphore->Count==0){
Status=PspWait(&Semaphore->WaitListHead,Milliseconds);
}
KeEnableInterrupts(IntState);//原子操作完成,恢复中断。
returnStatus;
}
2)修改PsReleaseSemaphore函数
STATUSPsReleaseSemaphore(INPSEMAPHORESemaphore,
INLONGReleaseCount,
OUTPLONGPreviousCount)
{
STATUSStatus;
BOOLIntState;
IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。
if(Semaphore->Count+ReleaseCount>Semaphore->MaximumCount){
Status=STATUS_SEMAPHORE_LIMIT_EXCEEDED;
}else{
//
//记录当前的信号量的值。
//
if(NULL!
=PreviousCount){
*PreviousCount=Semaphore->Count;
}
intOldCount=Semaphore->Count;
while((!
ListIsEmpty(&Semaphore->WaitListHead))
&&(ReleaseCount)){
PspWakeThread(&Semaphore->WaitListHead,
STATUS_SUCCESS);
PspThreadSchedule();
ReleaseCount--;
}
Semaphore->Count=OldCount+ReleaseCount;
Status=STATUS_SUCCESS;
}
KeEnableInterrupts(IntState);//原子操作完成,恢复中断。
returnStatus;
}
4.程序运行时的初值和运行结果
1)使用EOS的信号量解决生产者-消费者问题
使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码。
按F7生成修改后的EOS应用程序项目。
按F5启动调试。
OSLab会首先弹出一个调试异常对话框。
在调试异常对话框中选择“否”,继续执行。
立即激活虚拟机窗口查看生产者-消费者同步执行的过程,如图所示。
待应用程序执行完毕后,结束此次调试。
图6生产者-消费者同步执行开始
图7生产者-消费者同步执行结束
2)调试EOS信号量的工作过程
a)创建信号量
信号量结构体(SEMAPHORE)中的各个成员变量是由API函数CreateSemaphore的对应参数初始化的,查看main函数中创建Empty和Full信号量使用的参数有哪些不同,又有哪些相同,思考其中的原因。
按F5启动调试EOS应用项目。
OSLab会首先弹出一个调试异常对话框。
在调试异常对话框中选择“是”,调试会中断。
在main函数中创建Empty信号量的代码行(第77行)添加一个断点。
按F5继续调试,到此断点处中断。
按F11调试进入CreateSemaphore函数。
可以看到此API函数只是调用了EOS内核中的PsCreateSemaphoreObject函数来创建信号量对象。
图8PsCreateSemaphoreObject函数创建信号量对象
按F11调试进入semaphore.c文件中的PsCreateSemaphoreObject函数。
在此函数中,会在EOS内核管理的内存中创建一个信号量对象(分配一块内存),而初始化信号量对象中各个成员的操作是在PsInitializeSemaphore函数中完成的。
在semaphore.c文件的顶部查找到PsInitializeSemaphore函数的定义(第19行),在此函数的第一行(第39行)代码处添加一个断点。
按F5继续调试,到断点处中断。
观察PsInitializeSemaphore函数中用来初始化信号量结构体成员的值,应该和传入CreateSemaphore函数的参数值是一致的。
按F10单步调试PsInitializeSemaphore函数执行的过程,查看信号量结构体被初始化的过程。
打开“调用堆栈”窗口,查看函数的调用层次。
图9信号量结构体图10信号量结构体Count
图11信号量结构体MaximumCount图12信号量结构体WaitListHead
图13函数调用层次
b)等待、释放信号量
等待信号量(不阻塞)
生产者和消费者刚开始执行时,用来放产品的缓冲区都是空的,所以生产者在第一次调用WaitForSingleObject函数等待Empty信号量时,应该不需要阻塞就可以立即返回,直到完成PsWaitForSemaphore函数中的所有操作。
可以看到此次执行并没有进行等待,只是将Empty信号量的计数减少了1(由10变为了9)就返回了。
图13等待信号量(不阻塞)
释放信号量(不唤醒)
在Producer函数中释放Full信号量的代码行添加断点,进入PsReaseSemaphore函数,调试执行完成PsReleaseSemaphore函数中的所有操作,可以看到此次执行没有唤醒其它线程(因为此时没有线程在Full信号量上被阻塞),只是将Full信号量的计数增加了1(由0变为了1)。
图14等待信号量(不唤醒)
等待信号量(阻塞)
由于开始时生产者线程生产产品的速度较快,而消费者线程消费产品的速度较慢,所以当缓冲池中所有的缓冲区都被产品占用时,生产者在生产新的产品时就会被阻塞。
在“调用堆栈”窗口中双击Producer函数所在的堆栈帧,绿色箭头指向等待Empty信号量的代码行,查看Producer函数中变量i的值为14,表示生产者线程正在尝试生产14号产品。
图15生产者尝试生产14号产品
在“调用堆栈”窗口中双击PsWaitForSemaphore函数的堆栈帧,查看Empty信号量计数(Semaphore->Count)的值为-1,所以会调用PspWait函数将生产者线程放入Empty信号量的等待队列中进行等待(让出CPU)。
图16Empty信号量计数值减为-1
释放信号量(唤醒)
只有当消费者线程从缓冲池中消费了一个产品,从而产生一个空缓冲区后,生产者线程才会被唤醒并继续生产14号产品。
在eosapp.c文件的Consumer函数中,释放Empty信号量的代码行(第180行)添加一个断点。
按F5继续调试,到断点处中断。
查看Consumer函数中变量i的值为4,说明已经消费了4号产品。
按照3.3.2.2中的方法使用F10和F11调试进入PsReleaseSemaphore函数。
查看PsReleaseSemaphore函数中Empty信号量计数(Semaphore->Count)的值为-1,和生产者线程被阻塞时的值是一致的。
按F10单步调试PsReleaseSemaphore函数,直到在代码行(第132行)处中断。
此时Empty信号量计数的值已经由-1增加为了0,需要调用PspWakeThread函数唤醒阻塞在Empty信号量等待队列中的生产者线程(放入就绪队列中),然后调用PspSchedule函数执行调度,这样生产者线程就得以继续执行。
图17Empty信号量计数值增加为0
3)修改EOS的信号量算法
a)每次消费一个产品
图18程序开始执行
图19程序执行结束
b)每次消费两个产品
图20程序开始执行
图21程序执行结束
四、实验体会
通过使用信号量对象和互斥对象,我对一般进程同步的方法有了更加深入的认识;同时在实验调试中,我了解了信号量的工作方式,理解了进程同步的原理。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第六讲 进程的同步 第六 进程 同步