实验 5 进程的同步

实验 5 进程的同步

一、实验目的

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

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

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

二、实验内容

2.1准备实验

请读者按照下面方法之一在本地创建项目,用于完成本次实验:

方法一:从 CodeCode.net 平台领取任务

读者需要首先登录 CodeCode.net 平台领取本次实验对应的两个任务,从而在 CodeCode.net 平台上创建了两个个人项目,然后使用 OS Lab 提供的“从 Git 远程库新建项目”功能将这两个个人项目克隆到本地磁盘中。其中一个任务需要读者修改 EOS 内核程序,另一个任务需要读者修改 EOS 应用程序。

方法二:不从 CodeCode.net 平台领取任务

如果读者不使用 CodeCode.net 平台,需要按照下面的步骤创建项目:

\1. 使用 OS Lab 提供的“从 Git 远程库新建项目”功能直接将 EOS 内核实验模板克隆到本地磁盘中,创建一个 EOS 内核项目,实验模板的 URL 为

https://www.codecode.net/engintime/os-lab/Project-Template/ eos-kernel.git。

\2. 使用 OS Lab 提供的“从 Git 远程库新建项目”功能直接将 EOS 应用程序实验模板克隆到本地磁盘中,创建一个 EOS 应用程序项目,实验模板的 URL 为

https://www.codecode.net/engintime/os-lab/Project-Template/eos-app.g

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

1、 通过执行指导书 3.2 的 1-4 步骤,了解到了进程的同步是通过 mutex、empty 和 full 三个信号量实现的,通过函数 wait()和 release()控制进程进入临界区;三个同步操作不能颠倒,否则可能会出现死锁现象;

2、 生产者在生产了 13 号产品后本来要继续生产 14 号产品,可此时生产者为什么必须等待消费者消 费了 4 号产品后,才能生产 14 号产品呢?生产者和消费者是怎样使用同 步对象来实现该同步过程的呢?

答:这是因为临界资源的限制。临界资源是存放产品的缓冲池,只有等到缓冲池空闲的时候生产者才能生产东西,才能有权存放产品,因此只有等到消费者消费完产品,临界资源才会空前,才能继续生产 14 号产品。

img

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

2.3.1创建并初始化信号量

img

创建信号量结果如下:

image-20210606201608326

image-20210606201612144

第一行为 empty 信号量,初始值 10,最大值 10,第二个为 full 信号量,初始值为 0,最大 值为 10,说明信号量创建成功。

*2.3.2.2 释放信号量(不唤醒)*

释放信号量的结果

image-20210606201618951

因为生产者产出了一个产品,所以 empty 释放 1,full 增加 1,说明进程的运行过程中会影响相应的信号量的值。

*2.3.2.3 等待信号量(阻塞)*

运行结果如下

image-20210606201625646

image-20210606201628551

image-20210606201631353

*2.3.2.4 释放信号量(唤醒)*

执行指导书的步骤 4 得到如下结果

消费数

image-20210606201647180

执行指导书的步骤 7 得到如下结果

Empty 增至为 0

image-20210606201652875

此时生产者进程被唤醒,并开始生产第 14 号(第 15 个)产品。说明信号量 empty 通过是否为负数实现对进程的同步。

2.4 修改 EOS 的信号量算法

修改的具体内容如下:

PsWaitForSemaphore 函数中原有的代码段 Semaphore->Count-;

If (Semaphore->Count < 0) {

PspWait(&Semaphore->WaitListHead, INFINITE);

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

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

if (Semaphore->Count <= 0) {

PspWakeThread(&Semaphore- >WaitListHead, STATUS_ SUCCESS);

将 Producer 函数中等待 Empty 信号量的代码行

WaitForSingleObject(EmptySemaphoreHandle, INFINITE);

替换为 while(WAIT_ _TIMEOUT == WaitForSingleObject(EmptySemaphoreHandle,

300)){printf(“Producer wait for empty semaphore timeout\n”);

将Consumer函数中等待Full 信号量的代码行WaitForSingleObject(ullemaphoreHandle,

INFINITE);

替换为

while(WAIT_ _TIMEOUT == WaitForSingleObject(FullSemaphoreHandle,

  1. ){printf(“Consumer wait for full semaphore timeout\n”);

执行指导书的步骤 6,一次消费两个产品的结果图如下:

image-20210606201703897

说明当消费者消耗产品的速度略快时,生产者不会出现阻塞情况。

一、*思考题*

1、(思考题二)

****PsWaitForSemaphore 函数的流程图****:

①函数开始

②开始操作

③判断信号量是否小于 0 若 YES 则进行下一步,若 NO 则跳到第⑤步

④线程进入阻塞队列

⑤操作完成

⑥函数结束

*PsReleaseSemaphore 函数的流程图*

①函数开始

②开始操作

③判断 Semaphore->Count+ReleaseCount>Semaphore->Max immcount

(若 YES 则继续下一步操作 若 NO 则返回 Status=STATLS SEMPHORE LIMIT_EXEEDED 再跳到函数结束)

④记录当前信号量的值

⑤当前信号量的值加 1

⑥判断 Semaphore>Count<=0? 若 YES 则继续下一步,若 N0 则跳到第⑦步

⑦从阻塞队列唤醒线程

⑧返回 Status=STATUS_SECCESS

⑨函数结束

2、(思考题五)

LIMIT_EXEEDED 再跳到函数结束)

④记录当前信号量的值

⑤当前信号量的值加 1

⑥判断 Semaphore>Count<=0? 若 YES 则继续下一步,若 N0 则跳到第⑦步

⑦从阻塞队列唤醒线程

⑧返回 Status=STATUS_SECCESS

⑨函数结束

2、(思考题五)

答:申请两个资源信号量 empty 和 full,控制生产者线程和消费者线程之间的同步;只有当 empty>0 时,表示缓冲区有空闲,生产者线程可以进入临界区,每次线程结束后 empty-1;full+1。Empty<=0 时缓冲区已满,生产者线程阻塞。只有当 full>0 时,表示缓冲区内有产品,消费者可以进入临界区,每次线程结束后empty+1;full-1.full<=0 时缓冲区为空,消费者线程阻塞。

  • 8
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值