9. 在“调用堆栈”窗口中双击PsWaitForSemaphore函数的堆栈帧,查看Empty信号量计数(Semaphore->Count)的值为-1,所以会调用PspWait函数将生产者线程放入Empty信号量的等待队列中进行等待(让出CPU)。
10. 激活虚拟机窗口查看输出的结果。生产了从0到13的14个产品,但是只消费了从0到3的4个产品,所以缓冲池中的10个缓冲区就都被占用了,这与之前调试的结果是一致的。
3.3.2.4 释放信号量(唤醒)
只有当消费者线程从缓冲池中消费了一个产品,从而产生一个空缓冲区后,生产者线程才会被唤醒并继续生产14号产品。可以按照下面的步骤调试: 1. 删除所有断点。
2. 在eosapp.c文件的Consumer函数中,释放Empty信号量的代码行(第180)ReleaseSemaphor e (EmptySemaphoreHandle, 1, NULL); 添加一个断点。
3. 按F5继续调试,到断点处中断。
4. 查看Consumer函数中变量i的值为4,说明已经消费了4号产品。 5. 按照3.3.2.2中的方法使用F10和F11调试进入PsReleaseSemaphore函数。
6. 查看PsReleaseSemaphore函数中Empty信号量计数(Semaphore->Count)的值为-1,和生产者线程被阻塞时的值是一致的。
7. 按F10单步调试PsReleaseSemaphore函数,直到在代码行(第132行)
PspWakeThread(&Semaphore->WaitListHead, STATUS_SUCCESS); 处中断。此时Empty信号量计数的值已经由-1增加为了0,需要调用PspWakeThread函数唤醒阻塞在Empty信号量等待队列中的生产者线程(放入就绪队列中),然后调用PspSchedule函数执行调度,这样生产者线程就得以继续执行。
按照下面的步骤验证生产者线程被唤醒后,是从之前被阻塞时的状态继续执行的: 1. 在semaphore.c文件中PsWaitForSemaphore函数的最后一行(第83行)代码处添加一个断点。
2. 按F5继续调试,在断点处中断。
3. 查看PsWaitForSemaphore函数中Empty信号量计数(Semaphore->Count)的值为0,和生产者线程被唤醒时的值是一致的。
4. 在“调用堆栈”窗口中可以看到是由Producer函数进入的。激活Producer函数的堆栈帧,查看Producer函数中变量i的值为14,表明之前被阻塞的、正在尝试生产14号产品的生产者
线程已经从PspWait函数返回并继续执行了。 5. 结束此次调试。 3.4 修改EOS的信号量算法 修改处代码
运行成功
3.4.3 测试方法
修改完毕后,可以按照下面的方法进行测试:
1. 使用修改完毕的EOS Kernel项目生成完全版本的SDK文件夹,并覆盖之前的生产者-消费者应用程序项目的SDK文件夹。
2. 按F5调试执行原有的生产者-消费者应用程序项目,结果必须仍然与图13-2一致。如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,并重复步骤1。 3. 将Producer函数中等待Empty信号量的代码行
WaitForSingleObject(EmptySemaphoreHandle, INFINITE); 替换为 while(WAIT_TIMEOUT == WaitForSingleObject(EmptySemaphoreHandle, 300)){ printf(\empty semaphore timeout\\n\
相关推荐: