操作系统实验--进程的同步heu
操作系统中的进程同步与互斥

操作系统中的进程同步与互斥进程同步和互斥是操作系统中重要的概念和技术。
在多道程序环境中,多个进程同时运行,但它们之间存在着共享资源、互相依赖等情况,因此需要进行同步和互斥处理。
本文将从互斥与同步的定义、需求、常用的同步与互斥机制等方面进行论述。
一、互斥与同步的定义互斥是指某个资源同时只允许一个进程访问,其他进程需要等待。
同步是指一组相关进程在执行过程中需要相互合作,按照一定顺序执行。
二、互斥与同步的需求1. 互斥:当多个进程同时访问一个共享资源时,若不进行互斥处理,可能会引发数据不一致、竞争条件等问题。
例如,多个进程同时对一个文件进行写操作,可能导致文件内容错乱。
因此,需要通过互斥来保证每个进程访问共享资源的独占性,避免冲突。
2. 同步:在某些情况下,多个进程需要按照一定顺序执行,以满足某种逻辑关系或条件。
例如,生产者-消费者问题中,生产者需要在缓冲区未满时才能生产,消费者需要在缓冲区非空时才能消费。
因此,需要通过同步来协调进程的执行顺序。
三、常用的同步与互斥机制1. 互斥机制:常用的互斥机制包括信号量、互斥锁和临界区等。
a) 信号量:是一种用于控制对共享资源的访问的机制。
通过定义一个信号量,以保证同一时间只有一个进程可以访问共享资源。
典型的信号量包括二进制信号量和计数信号量。
b) 互斥锁:是一种用于协调多个进程访问共享资源的机制。
通过对共享资源加锁,只有持有锁的进程才能访问该资源,其他进程需要等待。
常见的互斥锁有互斥量(Mutex)和读写锁(ReadWrite Lock)等。
c) 临界区:是指一段在并发执行环境中,对某种共享资源进行操作的代码段。
在进入临界区之前,进程需要获取临界区的访问权限,执行完临界区代码后,释放访问权限。
通过临界区机制,可以保证同一时间只有一个进程在执行临界区的代码。
2. 同步机制:常用的同步机制包括信号量、条件变量和屏障等。
a) 信号量:除了用于互斥机制,信号量也可以用于同步机制。
进程的同步与互斥实验报告

进程的同步与互斥实验报告1.实验目的进程(线程)的同步与互斥是操作系统中非常重要的概念,本实验旨在通过实际操作,加深对这些概念的理解和掌握。
通过编写多个进程(线程),并在其间进行同步与互斥操作,验证同步与互斥的实际效果。
2.实验环境本实验在Linux系统下进行,使用C/C++语言编程。
3.实验内容3.1同步在实验中,我们编写了两个进程A和B,这两个进程需要按照特定的顺序执行。
为了实现同步,我们使用信号量机制来确保进程A和B按照正确的顺序执行。
3.2互斥在实验中,我们编写了多个进程C和D,这些进程需要同时对一个共享资源进行访问。
为了实现互斥,我们使用互斥锁机制来确保同一时刻只有一个进程访问共享资源。
4.实验过程4.1同步实验编写进程A和进程B的代码,使用信号量机制实现同步。
进程A先运行,然后通过信号量唤醒进程B,进程B再开始执行。
通过观察进程的运行顺序,验证同步机制是否起作用。
4.2互斥实验编写进程C和进程D的代码,使用互斥锁机制实现互斥。
进程C和进程D同时对一个共享资源进行访问,通过互斥锁来确保同一时刻只有一个进程访问共享资源。
观察进程的输出结果,验证互斥机制是否起作用。
5.实验结果5.1同步实验结果进程A开始执行进程A执行完毕进程B开始执行进程B执行完毕5.2互斥实验结果进程C开始执行进程C访问共享资源进程C执行完毕进程D开始执行进程D访问共享资源进程D执行完毕6.实验分析通过上述结果可以看出,同步实验中进程A和进程B按照正确的顺序执行,证明了同步机制的有效性。
互斥实验中进程C和进程D能够正确地交替访问共享资源,证明了互斥机制的有效性。
7.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。
同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。
在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。
操作系统实验一-进程同步

实验一进程同步一、实验目的:分析进程的同步与互斥现象,编程实现经典的进程同步问题——生产者与消费者问题的模拟,进一步加深对进程同步与互斥的理解。
二、实验内容:用C语言实现对生产者与消费者问题的模拟。
实验原理:生产者和消费者是经典的进程同步问题,在这个问题中,生产者不断的向缓冲区中写入数据,而消费者则从缓冲区中读取数据。
生产者进程和消费者对缓冲区的操作是互斥,即当前只能有一个进程对这个缓冲区进行操作,生产者进入操作缓冲区之前,先要看缓冲区是否已满,如果缓冲区已满,则它必须等待消费者进程将数据取出才能写入数据,同样的,消费者进程从缓冲区读取数据之前,也要判断缓冲区是否为空,如果为空,则必须等待生产者进程写入数据才能读取数据。
三、实验准备:1. 实现步骤:(1)分析计算机系统中对资源的分配与释放过程:计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
而当某个进程释放资源时,则它就相当一个生产者。
(2)定义生产者消费者问题中的各数据结构,并初始化信号量;(3)创建生产者与消费者进程,利用信号量实现生产者与消费者之间的同步与互斥;最后编程实现。
2. 相关函数:在实现的过程中需要用到以下API函数:(1)CreateThread()//该函数创建一个在调用进程的地址空间中执行的线程。
若线程创建成功,将返回该线程的句柄。
函数原型:HANDLE CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, //描述安全性,用NULL表示使用缺省值DWORD dwStackSize, //新线程拥有自己的堆栈,0表示使用缺省值1MB,推荐LPTHREAD_START_ROUTINE lpStartAddress, //新线程的起始地址,放线程函数名称LPVOID lpParameter,//此值被传送到线程函数去作为参数DWORD dwCreationFlags,//允许产生一个暂时挂起的线程,默认是0立即开始执行LPDWORD lpThreadld );//新线程的ID被传到这用法举例:hHandle1 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,0,(LPTHREAD_START_ROUTINE) ThreadName1,(LPVOID) NULL,0, &dwThreadID1 );(2)CreateMutex()函数可用来创建一个有名或无名的互斥量对象,函数返回值为互斥对象的句柄。
操作系统中的进程同步与互斥实现

操作系统中的进程同步与互斥实现在操作系统中,进程同步和互斥是非常重要的概念。
进程同步是确保多个进程在共享资源时按照特定的顺序进行访问,而互斥是确保在任何时候只能有一个进程访问共享资源。
本文将介绍进程同步和互斥的操作系统机制,并讨论它们在现代操作系统中的应用。
一、进程同步机制实际应用场景中,许多进程都需要共享某些资源。
在这种情况下,同步机制可以确保按照特定的顺序共享资源,以避免竞争和死锁。
1.信号量信号量是最常见的同步机制之一。
在操作系统中,信号量是一个计数器,用于记录共享资源的使用次数。
当进程需要访问资源时,它会尝试获取信号量。
如果资源当前没有被其他进程使用,信号量的值将减去1,并且进程将可以访问资源。
如果资源已经被其他进程使用,进程将被阻塞,直到资源可用。
当进程完成资源的使用时,它必须释放信号量,使其值增加1,以便其他进程可以访问该资源。
2.互斥锁互斥锁是一种更简单和更常见的同步机制,它用于确保共享资源仅由一个进程使用。
在操作系统中,互斥锁是一种执行阻塞锁的特殊锁。
如果一个进程想要访问一个共享资源,它必须先尝试获取互斥锁。
如果锁当前未被其他进程使用,则该进程将能够访问资源,锁将被锁定,以允许进程在访问资源时保持独占状态。
当进程完成访问资源时,它必须释放该锁,以便其他进程可以使用它。
3.条件变量条件变量是一种同步机制,用于仅在特定条件下执行操作。
条件变量由两个主要部分组成:条件和等待队列。
条件是一个布尔表达式,用于检查是否满足特定的条件。
等待队列是队列,其中包含在条件不满足时被阻塞的进程。
当条件被满足时,等待进程将被唤醒,并且可以开始执行所需的操作。
二、进程互斥机制在共享资源时,进程互斥是非常重要的。
这可以确保在任何时候仅有一个进程访问共享资源。
以下是三种常见的互斥机制的例子:1.临界区临界区是指只能由一个进程访问的代码部分。
在这种情况下,进程将在进入临界区之前获得互斥锁,以确保在任何时候只有一个进程可以访问临界区。
进程同步实验报告

一、实验目的1. 理解进程同步的概念和原理;2. 掌握进程同步的基本方法和机制;3. 学会使用信号量实现进程同步;4. 通过实验验证进程同步机制的有效性。
二、实验原理1. 进程同步:在多道程序设计中,进程的执行是并发的,但某些情况下需要保证多个进程按照一定的顺序执行,以避免出现数据不一致、死锁等问题。
进程同步是指通过某种机制,协调多个进程的执行顺序,保证它们能够正确、有效地共享资源。
2. 信号量:信号量是一种特殊的变量,用于实现进程同步。
信号量具有两个原子操作:P操作(wait)和V操作(signal)。
P操作用于申请资源,V操作用于释放资源。
3. 互斥锁:互斥锁是一种常见的进程同步机制,用于保证临界资源的互斥访问。
当一个进程进入临界区时,它会尝试获取互斥锁,如果锁已被其他进程获取,则该进程进入等待状态;当进程退出临界区时,它会释放互斥锁。
三、实验内容1. 实验环境:Linux操作系统,C语言编程环境。
2. 实验工具:gcc编译器、gdb调试器。
3. 实验步骤:(1)创建一个互斥锁,用于保护临界资源。
(2)编写两个进程,分别模拟对临界资源的访问。
(3)在进程访问临界资源前,使用P操作尝试获取互斥锁。
(4)在进程访问临界资源后,使用V操作释放互斥锁。
(5)编译并运行程序,观察进程执行情况。
四、实验结果与分析1. 实验结果:(1)在互斥锁的保护下,两个进程能够按照预期顺序访问临界资源。
(2)当其中一个进程正在访问临界资源时,另一个进程会进入等待状态。
(3)当进程访问临界资源完成后,它会释放互斥锁,允许其他进程访问。
2. 实验分析:(1)互斥锁能够有效地保护临界资源,避免数据不一致问题。
(2)信号量P操作和V操作保证了进程的同步,避免了死锁现象。
(3)通过实验验证了进程同步机制的有效性。
五、实验总结本次实验通过使用信号量和互斥锁,实现了进程同步。
实验结果表明,信号量和互斥锁能够有效地保证进程按照预期顺序执行,避免数据不一致和死锁等问题。
操作系统中进程同步和互斥的实现方法

操作系统中进程同步和互斥的实现方法在操作系统中,进程同步和互斥是非常重要的概念。
它们确保了并发程序的正确性和可靠性。
本文将介绍进程同步和互斥的实现方法。
一、进程同步在多任务环境中,不同的进程之间存在着相互依赖和相互制约的关系。
进程同步是为了协调进程之间的交互,使得它们在适当的时间进行合作,共同完成任务。
1. 互斥锁(Mutex)互斥锁是最常见的进程同步机制之一。
它通过给临界资源加锁,保证同一时刻只有一个进程可以访问该资源。
当一个进程占用了互斥锁后,其他进程试图访问该资源时会被阻塞,直到锁被释放。
2. 信号量(Semaphore)信号量是一种更加通用的进程同步机制。
它是一个计数器,用来控制多个进程对共享资源的访问。
当信号量的值大于等于1时,进程可以访问资源;当值为0时,进程被阻塞。
通过对信号量的操作(P/V操作),可以实现进程之间的同步和互斥。
3. 条件变量(Condition Variable)条件变量用于实现进程间的同步和通信。
当一个进程等待某个条件满足时,可以调用条件变量的等待操作来挂起它的执行;当条件满足时,其他进程可以通过唤醒操作通知等待的进程继续执行。
二、进程互斥进程互斥是为了防止多个进程同时访问或修改共享资源而引发的竞争条件和数据不一致问题。
它保证了同一时刻只有一个进程可以对共享资源进行操作,从而避免了竞争和冲突。
1. 临界区(Critical Section)临界区是一段代码,其中包含对共享资源的访问和操作。
为了实现进程的互斥访问,可以使用互斥锁、信号量等同步机制来对临界区进行保护。
一次只允许一个进程进入临界区,其他进程必须等待。
2. Peterson算法Peterson算法是一种经典的实现进程互斥的算法。
它利用了共享的标志和转弯顺序来实现两个进程之间的互斥访问。
然而,Peterson算法只适用于两个进程之间的互斥,对于多个进程之间的互斥并不适用。
3. 同步屏障(Barrier)同步屏障是一种常用的进程互斥机制。
操作系统进程调度和进程同步实验要求

0711操作系统进程调度和进程同步实验要求实验内容:用线程模拟进程,实现进程调度和进程同步。
在任意操作系统中,用c、c++或者java 编写程序。
并且完成相应的实验报告。
实验要求:实验一:进程调度⑴ 主线程,创建子线程,保存子线程的虚拟PCB(参见恐龙书P74)、要求运行多少时间(可随机产生)、已经等待多少时间(初始化为0),优先级(可随机产生)等信息,并负责子线程的调度。
调度的基本时间单位为1 S。
⑵ 创建20个线程(可以只用一个线程函数,传递不同的参数即上述数据结构)分别实现FCFS调度、SJF调度、RR调度、优先级调度和多级队列调度,并且计算每个调度的平均等待时间。
其中,多级队列调度要求设计4个调度队列,每个队列5个线程,队列内部分别采用FCFS、SJF、RR和优先级调度。
时间片的长度可以随机生成为n S。
⑶ 对于每个子线程,在其运行期间,输出其占用的时间标号(例如,第3个线程占用了第10秒的CPU时间,输出为:“Thread 3: 10”,格式可自行设计)。
实验二:进程同步⑴ 模拟哲学家就餐问题:设置5个子线程模拟5个哲学家,设置5个互斥区为筷子。
⑵ 输出问题解决方法:在每个哲学家线程中输出其获得的筷子标号与时间(可以读取系统时间,或者自行设置时间标准),例如:哲学家2在第n秒获得筷子1,在第m秒获得筷子2。
实验报告要求:写明实验目的、实验设计步骤、实验结果、总结。
附录:windows线程基本操作以windows线程函数为例介绍线程基本操作,以下函数都必须包含windows.h头文。
如果想更深入地了解线程,请参见《c++编程艺术》等相关书籍。
线程创建函数:HANDLE CreateThread (LPSECURITY_ATTRIBUTES secAttr,SIZE_T stackSize,LPTHREAD_START_ROUTINE threadFunc,LPVOID param,DWORD flags,LPDWORD threadID);在此,secAttr是一个用来描述线程的安全属性的指针。
操作系统的进程同步与互斥

操作系统的进程同步与互斥操作系统是计算机系统中最核心的组成部分之一,它负责管理计算机资源和协调各个应用程序的执行。
在多任务处理的环境下,不同的进程可能会同时访问共享资源,为了保证数据的一致性和避免竞争条件的出现,操作系统引入了进程同步与互斥机制。
本文将深入探讨操作系统中进程同步与互斥的原理和实现方式。
一、进程的概念和特点进程是操作系统中的基本执行单元,它是一个正在执行中的程序的实例。
进程是临时的,动态的,具有独立的内存空间和执行环境,通过操作系统的调度器来进行管理和调度。
每个进程都有自己的执行序列,独立的内存空间和上下文环境。
进程的特点包括:并发性、独立性、异步性和共享性。
并发性指的是多个进程可以同时存在于内存中,并且可以以任意的次序进行执行。
独立性体现在每个进程都拥有独立的执行序列和内存空间,彼此之间不会相互影响。
异步性是指进程的执行是由操作系统的调度器决定的,进程之间的执行顺序是不可预测的。
共享性是指多个进程可以同时访问和共享系统资源。
二、进程同步的概念和原因进程同步是指进程之间按照一定的规定,按照一定的次序来访问和使用共享资源的过程。
在多个进程同时访问共享资源的情况下,如果没有进行进程同步,就会导致数据的不一致性和竞争条件的发生。
因此,进程同步是操作系统必须解决的一个重要问题。
进程同步的原因主要有以下几点:互斥访问资源、合作共享资源、数据的一致性和死锁的避免。
互斥访问资源是指多个进程需要对共享资源进行访问时,要求只有一个进程可以访问该资源,其他进程必须等待。
合作共享资源是指多个进程之间需要协同工作,共同完成某个任务,如生产者-消费者问题。
数据的一致性要求多个进程在访问和修改数据时能够保持数据的正确性和完整性。
死锁是指进程之间因为争夺资源而相互等待,导致系统无法继续运行。
三、进程同步与互斥的实现方式为了实现进程同步与互斥,操作系统提供了一些机制和算法。
其中比较常用的有:临界区、互斥量、信号量和条件变量。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统实验报告哈尔滨工程大学计算机科学与技术学院第六讲进程的同步一、实验概述1. 实验名称进程的同步2. 实验目的(1)使用EOS 的信号量编程解决生产者—消费者问题,理解进程同步的意义。
(2)调试跟踪EOS 的信号量的工作过程,理解进程同步的原理。
(3)修改EOS 的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。
3. 实验类型验证型实验,设计性实验4. 实验内容(1)准备实验(2)使用 EOS 的信号量解决生产者-消费者问题(3)调试 EOS 信号量的工作过程1)创建信号量2)等待释放信号量3)等待信号量(不阻塞)4)释放信号量(不唤醒)5) 等待信号量(阻塞)6) 释放信号量(唤醒)(4)修改 EOS 的信号量算法二、实验环境操作系统集成实验环境OS Lab三、实验过程1. 设计思路和流程图2. 算法实现3. 需要解决的问题及解答(1). P143生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢生产者和消费者是怎样使用同步对象来实现该同步过程的呢答:此时生产了0-13号14个产品,消费了0-3号4个产品,缓冲区都占满了。
只有缓冲区有空闲生产者才能生产东西,有权向里面放东西。
所以它必须等到消费者,取走产品,有空闲缓冲区时,才继续生产14号产品。
(2). 修改EOS的信号量算法(只看一次消费1个产品的,一次消费2个产品的可以写到实验报告中)答:见三,四部分(3). 思考在ps/文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作答:原子操作要求一旦开始就要运行到结束,不能有中断。
在执行等待信号量和释放信号量的时候,不允许cpu响应外部中断,所以使用原子操作。
(4). 绘制ps/文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。
PsWaitForSemaphorePs Release Semaphore原子操作前关中断开始原子操作P操作P操作结束Wait操作的信号量大于0Y执行P操作N4. 主要数据结构、实现代码及其说明1)修改PsWaitForSemaphore函数if (Semaphore->Count>0){Semaphore->Count--;flag=STATUS_SUCCESS;}源程序并附上注释#include ""VOIDPsInitializeSemaphore(IN PSEMAPHORE Semaphore,IN LONG InitialCount,IN LONG MaximumCount)/*++功能描述:初始化信号量结构体。
参数:Semaphore -- 要初始化的信号量结构体指针。
InitialCount -- 信号量的初始值,不能小于0 且不能大于MaximumCount。
MaximumCount -- 信号量的最大值,必须大于0。
返回值:无。
--*/{ASSERT(InitialCount >= 0 && InitialCount <= MaximumCount && MaximumCount > 0);Semaphore->Count = InitialCount;Semaphore->MaximumCount = MaximumCount;ListInitializeHead(&Semaphore->WaitListHead);}STATUSPsWaitForSemaphore(IN PSEMAPHORE Semaphore,IN INT Milliseconds,IN STATUS i)/*++功能描述:信号量的Wait 操作(P 操作)。
参数:Semaphore -- Wait 操作的信号量对象。
Milliseconds -- 等待超时上限,单位毫秒。
返回值:STATUS_SUCCESS。
当你修改信号量使之支持超时唤醒功能后,如果等待超时,应该返回STA TUS_TIMEOUT。
--*/{BOOL IntState;ASSERT(KeGetIntNesting() == 0); 程序运行时的初值和运行结果(1)准备实验1)启动 OS Lab。
2)新建一个 EOS Kernel 项目。
3)生成 EOS Kernel 项目,从而在该项目文件夹中生成 SDK 文件夹。
4)新建一个 EOS 应用程序项目。
5)使用在第 3 步生成的 SDK 文件夹覆盖 EOS 应用程序项目文件夹中的 SDK 文件夹。
(2)使用EOS的信号量解决生产者-消费者问题1)使用文件中的源代码,替换之前创建的 EOS 应用程序项目中文件内的源代码。
2)按 F7 生成修改后的 EOS 应用程序项目。
3)按 F5 启动调试。
OS Lab 会首先弹出一个调试异常对话框。
4)在调试异常对话框中选择“否”,继续执行。
5)立即激活虚拟机窗口查看生产者-消费者同步执行的过程。
6)待应用程序执行完毕后,结束此次调试。
(3)调试EOS信号量的工作过程1)创建信号量○1按 F5 启动调试 EOS 应用项目。
OS Lab 会首先弹出一个调试异常对话框。
○2在调试异常对话框中选择“是”,调试会中断。
○3在 main 函数中创建 Empty 信号量的代码行(第 77 行)EmptySemaphoreHandle = CreateSemaphore(BUFFER_SIZE, BUFFER_SIZE, NULL); 添加一个断点。
○4按 F5 继续调试,到此断点处中断。
○5按 F11 调试进入 CreateSemaphore 函数。
可以看到此 API 函数只是调用了 EOS 内核中的PsCreateSemaphoreObject 函数来创建信号量对象。
○6按 F11 调试进入文件中的 PsCreateSemaphoreObject 函数。
在此函数中,会在 EOS内核管理的内存中创建一个信号量对象(分配一块内存),而初始化信号量对象中各个成员的操作是在PsInitializeSemaphore 函数中完成的。
○7在文件的顶部查找到 PsInitializeSemaphore 函数的定义(第 19 行),在此函数的第一行(第39 行)代码处添加一个断点。
○8按 F5 继续调试,到断点处中断。
观察 PsInitializeSemaphore 函数中用来初始化信号量结构体成员的值,应该和传入 CreateSemaphore 函数的参数值是一致的。
○9按 F10 单步调试 PsInitializeSemaphore 函数执行的过程,查看信号量结构体被初始化的过程。
打开“调用堆栈”窗口,查看函数的调用层次。
2)等待信号量(不阻塞)○1删除所有的断点(防止有些断点影响后面的调试)。
○2在文件的 Producer 函数中,等待 Empty 信号量的代码行(第 144 行)WaitForSingleObject(EmptySemaphoreHandle, INFINITE); 添加一个断点。
○3按 F5 继续调试,到断点处中断。
○WaitForSingleObject 函数最终会调用内核中的 PsWaitForSemaphore 函数完成等待操作。
所以,在文件中 PsWaitForSemaphore 函数的第一行(第 68 行)添加一个断点。
○5按 F5 继续调试,到断点处中断。
○6按 F10 单步调试,直到完成 PsWaitForSemaphore 函数中的所有操作。
可以看到此次执行并没有进行等待,只是将 Empty 信号量的计数减少了 1(由 10 变为了 9)就返回了。
3)释放信号量(不唤醒)○1删除所有的断点(防止有些断点影响后面的调试)。
○2在文件的 Producer 函数中,释放 Full 信号量的代码行(第 152 行)ReleaseSemaphore(FullSemaphoreHandle, 1, NULL); 添加一个断点。
○3按 F5 继续调试,到断点处中断。
○4按 F11 调试进入 ReleaseSemaphore 函数。
○5继续按 F11 调试进入 PsReleaseSemaphoreObject 函数。
○6先使用 F10 单步调试,当黄色箭头指向第 269 行时使用 F11 单步调试,进入PsReleaseSemaphore函数。
○7按 F10 单步调试,直到完成 PsReleaseSemaphore 函数中的所有操作。
可以看到此次执行没有唤醒其它线程(因为此时没有线程在 Full 信号量上被阻塞),只是将 Full 信号量的计数增加了 1(由 0 变为了 1)。
4)等待信号量(阻塞)○1结束之前的调试。
○2删除所有的断点。
○3按 F5 重新启动调试。
OS Lab 会首先弹出一个调试异常对话框。
○4在调试异常对话框中选择“是”,调试会中断。
○5在文件中的 PsWaitForSemaphore 函数的PspWait(&Semaphore->WaitListHead, INFINITE); 代码行(第 78 行)添加一个断点。
○6按 F5 继续调试,并立即激活虚拟机窗口查看输出。
开始时生产者、消费者都不会被信号量阻塞,同步执行一段时间后才在断点处中断。
○7中断后,查看“调用堆栈”窗口,有 Producer 函数对应的堆栈帧,说明此次调用是从生产者线程函数进入的。
○8在“调用堆栈”窗口中双击 Producer 函数所在的堆栈帧,绿色箭头指向等待 Empty 信号量的代码行,查看 Producer 函数中变量 i 的值为 14,表示生产者线程正在尝试生产 14 号产品。
○在“调用堆栈”窗口中双击 PsWaitForSemaphore 函数的堆栈帧,查看 Empty 信号量计数(Semaphore->Count)的值为-1,所以会调用 PspWait 函数将生产者线程放入 Empty 信号量的等待队列中进行等待(让出 CPU)。
○激活虚拟机窗口查看输出的结果。
生产了从 0 到 13 的 14 个产品,但是只消费了从 0 到 3 的 4 个产品,所以缓冲池中的 10 个缓冲区就都被占用了,这与之前调试的结果是一致的。
5)释放信号量(唤醒)○1删除所有断点。
○2在文件的 Consumer 函数中,释放 Empty 信号量的代码行(第 180 行)ReleaseSemaphore(EmptySemaphoreHandle, 1, NULL); 添加一个断点。