// 创建子进程成功,等待子进程运行结束。 //
WaitForSingleObject(ProcInfoOne[i].ProcessHandle, INFINITE); //WaitForSingleObject(ProcInfoTwo.ProcessHandle, INFINITE);
//
// 得到并输出子进程的退出码。 //
GetExitCodeProcess(ProcInfoOne[i].ProcessHandle, &ulExitCode); printf(\
//GetExitCodeProcess(ProcInfoTwo.ProcessHandle, &ulExitCode); //printf(\
//
// 关闭不再使用的句柄。 //
CloseHandle(ProcInfoOne[i].ProcessHandle); CloseHandle(ProcInfoOne[i].ThreadHandle); //CloseHandle(ProcInfoTwo.ProcessHandle); //CloseHandle(ProcInfoTwo.ThreadHandle);
} else {
printf(\Failed, Error code: 0x%X.\\n\GetLastError()); nResult = 1; } }
return nResult; }
实验四:线程的状态和转换
一、实验目的:
1、调试线程在各种状态间的转换过程,熟悉线程的状态和转换。 2、通过为线程增加挂起状态,加深对线程状态的理解。 二、实验内容及步骤:
1、准备实验:新建一个EOS Kernel项目。 2、调试线程状态的转换过程:对第一步的项目启动调试,待EOS启动完毕,在EOS控制台中输入命令“loop”后按回车。得到结果:
结束调试。
1. 控制台派遣线程被唤醒,由阻塞状态进入就绪状态。 2. loop线程由运行状态进入就绪状态。 3. 控制台派遣线程由就绪状态进入运行状态。
4. 待控制台派遣线程处理完毕由于空格键被按下而产生的键盘事件后,派遣线程会由运行状态重新进入阻塞状态,开始等待下一个键盘事件到来。 5. loop线程由就绪状态进入运行状态,继续执行死循环。
按F5继续执行,在PspSelectNextThread函数中的断点处中断。。 按F5继续执行,在PspUnreadyThread函数中的断点处中断。在快速监视对话框中查看“*Thread”表达式的值。关闭快速监视对话框后,在“调用堆栈”窗口中激活PspSelectNextThread函数对应的堆栈项,在“调用堆栈”窗口中激活PspUnreadyThread函数对应的堆栈项,然后按F10单步调试,直到返回PspSelectNextThread函数并将线程状态修改为Running。
按F5继续执行,在PspWait函数中的断点处中断。
3、为线程增加挂起状态:删除之前添加的所有断点。 按F5启动调试。 待EOS启动完毕,在EOS控制台中输入命令“loop”后按回车。此时可以看到loop线程的执行计数在不停增长,说明loop线程正在执行。记录下loop线程的ID。 按Ctrl+F2切换到控制台2,输入命令“suspend 31”(如果loop线程的ID是31)后按回车。命令执行成功的结果如图12-2所示。 按Ctrl+1切换回控制台1,可以看到由于loop线程已经成功被挂起,其执行计数已经停止增长了。此时占用处理器的是EOS中的空闲线程。
Resume原语可以将一个被Suspend原语挂起的线程(处于静止就绪状态)恢复为就绪状态。但是PsResumThread函数中的这部分代码(第119行),完成这部分代码。 代码:/*
提供该示例代码是为了阐释一个概念,或者进行一个测试,并不代表着 最安全的编码实践,因此不应在应用程序或网站中使用该示例代码。 */
STATUS
PsResumThread(
IN HANDLE hThread ) /*++
功能描述:
恢复指定的线程。
参数:
hThread - 需要被恢复的线程的句柄。
返回值:
如果成功则返回 STATUS_SUCCESS。 --*/ {
STATUS Status; BOOL IntState; PTHREAD Thread;
//
// 根据线程句柄获得线程对象的指针 // Status = ObRefObjectByHandle(hThread, PspThreadType, (PVOID*)&Thread);
if (EOS_SUCCESS(Status)) {
IntState = KeEnableInterrupts(FALSE); // 关中断
if (Zero == Thread->State) {
//
// 将线程从挂起线程队列中移除。 //
ListRemoveEntry(&Thread->StateListEntry); //
// 将挂起的线程恢复为就绪状态。 // 线程由静止就绪状态(Static Ready)进入活动就绪状态(Active Ready)。
//
PspReadyThread(Thread); //
// 执行线程调度,让刚刚恢复的线程有机会执行(如果真的能够调度到它的话)。 //
PspThreadSchedule();
Status = STATUS_SUCCESS;
} else {
Status = STATUS_NOT_SUPPORTED; }
KeEnableInterrupts(IntState); // 开中断
ObDerefObject(Thread); }
return Status; }
测试方法 :
待读者完成Resume原语后,可以先使用suspend命令挂起loop线程,然后在控制台2中输入命令“Resume 31”(如果loop线程的ID是31)后按回车。
思考题:思考一下,在本实验中,当loop线程处于运行状态时, EOS 中还有哪些线程,它们分别处于什么状态。可以使用控制台命令pt查看线程的状态。
三、实验总结:
明白了loop指令的用法以及resume原语的结构。
实验五:进程的同步
一、实验目的:
1、使用EOS的信号量,编程解决生产者—消费者问题,理解进程同步的意义。 2、调试跟踪EOS信号量的工作过程,理解进程同步的原理。
3、修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。 二、实验内容和步骤: 1、准备实验:新建一个EOS Kernel项目。 生成EOS Kernel项目,从而在该项目文件中生成SDK文件夹。新建一个EOS应用程序项目。使用在第3步生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。
2、使用EOS的信号量解决生产者-消费者问题:在本实验文件夹中,提供了使用EOS的信号量解决生产者-消费者问题的参考源代码文件pc.c,仔细阅读此文件中的源代码和注释。使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码。按F5启动调试。立即激活虚拟机窗口查看生产者-消费者同步执行的过程。 结果:
3、调试EOS信号量的工作过程:启动调试,在main函数中创建Empty信号量的代码行添加一个断点。按F5继续调试,到此断点处中断。按F11调试进入CreateSemaphore函数。可以看到此API函数只是调用了EOS内核中的PsCreateSemaphoreObject函数来创建信号量对象。按F11调试进入semaphore.c文件中的PsCreateSemaphoreObject函数。在semaphore.c文件的顶部查找到PsInitializeSemaphore函数的定义(第19行),在此函数的第一行(第39行)代码处添加一个断点。按F5继续调试,到断点处中断。观察PsInitializeSemaphore
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库华北电力大学 操作系统实验报告(3)在线全文阅读。
相关推荐: