进程的同步实验报告解析.docx

上传人:b****4 文档编号:734800 上传时间:2022-10-12 格式:DOCX 页数:14 大小:295.71KB
下载 相关 举报
进程的同步实验报告解析.docx_第1页
第1页 / 共14页
进程的同步实验报告解析.docx_第2页
第2页 / 共14页
进程的同步实验报告解析.docx_第3页
第3页 / 共14页
进程的同步实验报告解析.docx_第4页
第4页 / 共14页
进程的同步实验报告解析.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

进程的同步实验报告解析.docx

《进程的同步实验报告解析.docx》由会员分享,可在线阅读,更多相关《进程的同步实验报告解析.docx(14页珍藏版)》请在冰豆网上搜索。

进程的同步实验报告解析.docx

进程的同步实验报告解析

操作系统

实验报告

课程名称

操作系统实验

课程编号

0906553

实验项目名称

进程的同步

学号

年级

姓名

专业

计算机科学与技术

学生所在学院

计算机科学与技术学院

指导教师

实验室名称地点

 

哈尔滨工程大学

计算机科学与技术学院

进程的同步

一.实验概述

1.实验名称:

进程的同步

2.实验目的:

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

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

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

3.实验类型:

验证+设计

4.实验内容:

1)准备实验

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

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

4)修改EOS的信号量算法

二.实验环境

操作系统:

windowsXP

编译器:

TevalatonOSLab

语言:

C

三.实验过程

1.设计思路和流程图

2.实验过程

1)准备实验,启动OSLab,新建一个EOSKernel项目和EOS应用程序,将EOSKernel项目中生成的SDK文件覆盖到ROS应用程序项目文件夹中的SDK文件夹;

2)使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件中的代码,并生成项目,启动调试,忽略调试的异常,立即激活虚拟机窗口中查看生产者-消费者同步执行的过程,结束此次调试;

3)信号量结构体(SEMAPHORE)中的各个成员变量是由API函数CreateSemaphore的对应参数初始化的。

创建信号量,启动调试EOS应用程序,在OSLab弹出的调试异常对话框中选择“是”,进入异常调试,在main函数中创建Empty信号量的代码行添加断点;

EmptySemaphoreHandle=CreateSemaphore(BUFFER_SIZE,BUFFER_SIZE,NULL);

4)启动调试,逐语句调试进入CreateSemaphore函数。

可以看到此API函数只是调用了EOS内核中的PsCreateSemaphoreObject函数来创建信号量对象,继续逐语句调试试进入semaphore.c文件中的PsCreateSemaphoreObject函数。

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

5)在semaphore.c文件的顶部查找到PsInitializeSemaphore函数的定义,在此函数的第一行代码处添加一个断点,继续调试,,到断点处中断。

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

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

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

7)等待信号量(不阻塞),删除所有的断点(防止有些断点影响后面的调试),在eosapp.c文件的Producer函数中,等待Empty信号量的代码行添加一个断点;

WaitForSingleObject(EmptySemaphoreHandle,INFINITE);

8)继续调试,到断点处中断,WaitForSingleObject函数最终会调用内核中的PsWaitForSemaphore函数完成等待操作。

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

在断点处中断后,逐过程调试,直到完成PsWaitForSemaphore函数中的所有操作。

可以看到此次执行并没有进行等待,只是将Empty信号量的计数减少了1(由10变为了9)就返回了;

9)释放信号量(不阻塞),生产者和消费者刚开始执行时,用来放产品的缓冲区都是空的,所以生产者在第一次调用WaitForSingleObject函数等待Empty信号量时,应该不需要阻塞就可以立即返回;

删除所有的断点(防止有些断点影响后面的调试),在eosapp.c文件的Producer函数中,等待Empty信号量的代码行添加一个断点;

WaitForSingleObject(EmptySemaphoreHandle,INFINITE);

10)继续调试,到断点处中断,WaitForSingleObject函数最终会调用内核中的PsWaitForSemaphore函数完成等待操作。

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

11)继续调试,在断点处中断,逐过程单步调试,,直到完成PsWaitForSemaphore函数中的所有操作。

可以看到此次执行并没有进行等待,只是将Empty信号量的计数减少了1(由10变为了9)就返回了;

12)释放信号量(不唤醒),删除所有的断点(防止有些断点影响后面的调试),在eosapp.c文件的Producer函数中,释放Full信号量的代码行添加一个断点。

ReleaseSemaphore(FullSemaphoreHandle,1,NULL);

13)继续调试,到断点处中断,逐语句调试进入ReleaseSemaphore函数,继续按F11调试进入PsReleaseSemaphoreObject函数,使用F10单步调试,当黄色箭头指向第269行时使用F11单步调试,进入PsReleaseSemaphore函数,继续单步调试,直到完成PsReleaseSemaphore函数中的所有操作。

可以看到此次执行没有唤醒其它线程(因为此时没有线程在Full信号量上被阻塞),只是将Full信号量的计数增加了1(由0变为了1)。

生产者线程通过等待Empty信号量使空缓冲区数量减少了1,通过释放Full信号量使满缓冲区数量增加了1,这样就表示生产者线程生产了一个产品并占用了一个缓冲区;

14)等待信号量(阻塞),由于开始时生产者线程生产产品的速度较快,而消费者线程消费产品的速度较慢,所以当缓冲池中所有的缓冲区都被产品占用时,生产者在生产新的产品时就会被阻塞。

结束之前的调试,删除所有的断点,按F5重新启动调试,选择异常调试;

15)在semaphore.c文件中的PsWaitForSemaphore函数的代码行(第78行)添加一个断点;

PspWait(&Semaphore->WaitListHead,INFINITE);

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

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

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

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

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

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

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

20)释放信号量(唤醒),只有当消费者线程从缓冲池中消费了一个产品,从而产生一个空缓冲区后,生产者线程才会被唤醒并继续生产14号产品。

删除所有断点,在eosapp.c文件的Consumer函数中,释放Empty信号量的代码行添加一个断点。

ReleaseSemaphore(EmptySemaphoreHandle,1,NULL);

21)继续调试,到断点处中断,查看Consumer函数中变量i的值为4,说明已经消费了4号产品。

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

23)逐过程单步调试PsReleaseSemaphore函数,直到在代码行处中断。

PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS);

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

24)在semaphore.c文件中PsWaitForSemaphore函数的最后一行(第83行)代码处添加一个断点,继续调试,在断点处中断,查看PsWaitForSemaphore函数中Empty信号量计数(Semaphore->Count)的值为0,和生产者线程被唤醒时的值是一致的。

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

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

26)修改EOS的信号量算法。

修改PsWaitForSemaphore函数:

①对于支持等待超时唤醒功能的信号量,其计数值只能是大于等于0。

当计数值大于0时,表示信号量为signaled状态;当计数值等于0时,表示信号量为nonsignaled状态。

所以,值等于0时,调用PspWait函数阻塞线程的执行(将参数Milliseconds做为PspWait函数的第二个参数,并使用PspWait函数的返回值做为返回值);

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

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

③在EOSKernel项目ps/sched.c文件查看PspWait函数的说明和源代码;

Satus=flag;

if(Semaphore->Count>0){

Semaphore->Count--;

flag=STATUS_SUCCESS;

}

elseif(Semaphore->Count==0)

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

修改PsReleaseSemaphore函数:

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

②如果

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

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1