计算机操作系统实验指导.doc

上传人:仙人指路1688 文档编号:2882197 上传时间:2023-03-01 格式:DOC 页数:177 大小:8.32MB
返回 下载 相关 举报
计算机操作系统实验指导.doc_第1页
第1页 / 共177页
计算机操作系统实验指导.doc_第2页
第2页 / 共177页
计算机操作系统实验指导.doc_第3页
第3页 / 共177页
计算机操作系统实验指导.doc_第4页
第4页 / 共177页
计算机操作系统实验指导.doc_第5页
第5页 / 共177页
点击查看更多>>
资源描述

《计算机操作系统实验指导.doc》由会员分享,可在线阅读,更多相关《计算机操作系统实验指导.doc(177页珍藏版)》请在三一办公上搜索。

1、第二章 windows的进程管理2.1 实验一:线程的创建与撤销2.1.1 实验目的(1)熟悉windows系统提供的线程创建与撤销系统调用.(2)掌握windows系统环境下线程的创建与撤销方法.2.1.2 实验准备知识1.线程的创建CeateThread()完成线程的创建.它在调用进程的地址空间上创建一个线程,执行指定的函数,并返回新建立的线程的句柄.原型:HANDLE CeateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPSECURITY_START_ROUTINE lpStartAddress,

2、LPVOID lpparameter,DWORD dwCreationFlags,LPDWORD lpThreadId);参数说明:(1)lpThreadAttributes:为线程指定安全属性.为NULL时,线程得到一个默认的安全描述符.(2)dwStackSize:线程堆栈的大小.其值为0时,其大小与调用该线程的线程堆栈大小相同.(3)lpStartAddress:指定线程要执行的函数.(4)lpparameter:函数中要传递的参数.(5)dwCreationFlags:指定线程创建后所处的状态.若为CRRATE_SUSPENDED,表示创建后出于挂起状态,用ResumeThread()

3、激活线程才可以执行.若该值为0,表示线程创建后立即执行.(6)lpThreadId:用一个32位的变量接受系统返回的线程标识符.若该值设为NULL,系统不返回线程标识符.返回值:如果线程创建成功,将返回线程的句柄;如果失败,系统返回NULL,可以调用函数GetLastError查询失败的原因.用法举例:static HANDLE hHandle1=NULL; /用于存储线程返回句柄的变量DWORD dwThreadID1; /用于存储线程标识符的变量/创建一个名为ThreadName1的线程hHandle1=CeateThread(LPSECURITY_ATTRIBUTES) NULL 0,

4、(LPSECURITY_START_ROUTINE)ThreadName1, (LPDWORD)NULL, 0,&dwThreadID1);2.撤销进程ExitThread()用于撤销当前进程.原型:VOID ExitThread(DWORD dwExitCode); /线程返回码参数说明:dwExitCode:指定线程返回码,可以调用GetExitCodeThread()查询返回码的含义.返回值:该函数没有返回值.用法举例:ExitThread(0); /参数0表示要撤销进程中的所有线程3.终止线程TerminateThread()用于终止当前线程.该函数与ExitThread()的区别在于

5、,ExitThread()在撤销线程时将该线程所拥有的资源全部归还给系统,而TerminateThread()不归还资源.原型:BOOL TerminateThread(HANDLE hHandle, /线程句柄DWORD dwExitCode); /线程返回码参数说明:(1)hThread:要终止线程的线程句柄.(2)dwExitCode:指定线程返回码,可以调用GetExitCodeThread()查询返回码的含义.返回值:函数调用成功,将返回一个非0值;若失败,返回0,可以调用函数GetLastError()查询失败的原因.4.挂起线程Sleep()用于挂起当前正在执行的线程.原型:VO

6、ID Sleep(DWORD dwMilliseconds);参数说明:dwMilliseconds;指定挂起时间,单位为ms(毫秒).返回值:该函数没有返回值.5.关闭句柄函数CloseHandle()用于关闭已打开的对象的句柄,其作用与释放动态申请的内存空间类似,这样可以释放系统资源,使线程安全运行.原型:BOOL CloseHandle(HANDLE hObject);参数说明:hObject:已打开对象的句柄.返回值:如果函数调用成功,则返回值为非0值;如果函数调用失败,则返回值为0.若要得到更多的错误信息,调用函数GetLastError()查询.2.1.3实验内容使用系统调用Cre

7、atThread()创建一个子线程,并在子线程中显示;Thread is Running!.为了能让用户清楚地看到线程的运行情况,使用Sleep()使线程挂起5s,之后使用ExitThread(0)撤销进程.2.1.4实验要求能正确使用CreatThread(),ExitThread()及Sleep()等系统调用,进一步理解进程与线程理论.2.1.5实验指导本实验在WindowsXP,Microsoft Visual C+ 6.0环境下实现,利用Windows SDK提供的API完成程序的功能.实验在Windows XP环境下安装由于WindowsXP,Microsoft Visual C+

8、6.0是一个集成开发环境,其中包含了Windows SDK 所有工具和定义,所以安装了WindowsXP,Microsoft Visual C+ 6.0后不用特意安装SDK.试验中所有的API是操作系统提供的用来进行应用程序开发的系统功能接口.(1)首先启动安装好的,Microsoft Visual C+ 6.0.(2)在,Microsoft Visual C+ 6.0环境下选择File-new命令,然后在Project选项卡中选择Win32 Console Application建立一个控制台工程文件.(3)由于CreatThread()等函数是Microsoft Windows操作系统的系

9、统调用,因此,在下图中选择An application that supports MFC,之后单击Finish按钮.(4)之后将打开,Microsoft Visual C+ 6.0编辑环境(见下图),按本实验的要求编辑C程序,之后编辑,链接并运行该程序即可.2.1.6实验总结在Windows系统中进程是资源的拥有者,线程是系统调用的单位.进程创建后,其主线程也随即被创建.在该实验中,有创建了一个名为ThreadName1的子线程,该子线程与主线程并并发的被系统调度.为了能让用户清楚地看到线程的运行情况,在主线程创建了子线程之后,将主线程挂起5s,以确保子线程能够运行完毕,之后调用ExitTh

10、read(0)将所有线程撤销.线程运行如下图所示.2.1.7 源程序/ ThreadCreate.cpp : Defines the entry point for the console application./#include stdafx.h#include ThreadCreate.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ The one and only application objectCWinApp theApp;using namespa

11、ce std;void ThreadName()printf(Thread is Running!n);static HANDLE hHandle1=NULL; / /需要改成hHandleDWORD ThreadID1; /需要改成ThreadID int _tmain(int argc, TCHAR* argv, TCHAR* envp)int nRetCode = 0; hHandle=CreateThread(LPSECURITY_ATTRIBUTES) NULL,0,(LPTHREAD_START_ROUTINE) ThreadName,(LPVOID)NULL,0,&ThreadI

12、D);ThreadName(); /需要在这里添加一个调用ThreadName()1; /需要在这里添加一个调用Sleep(5000);CloseHandle(hHandle);ExitThread(0);return nRetCode; / initialize MFC and print and error on failureif (!AfxWinInit(:GetModuleHandle(NULL), NULL, :GetCommandLine(), 0)/ TODO: change error code to suit your needscerr _T(Fatal Error: M

13、FC initialization failed) endl;nRetCode = 1;else/ TODO: code your applications behavior here.CString strHello;strHello.LoadString(IDS_HELLO);cout (LPCTSTR)strHello endl;return nRetCode;void ThreaName1()Printf(“Thread is Runing!n”);2.1.8 实验展望可以进一步完善程序功能,请思考以下问题.(1)如何向线程对应的函数传递参数?一个参数如何传递,多个参数又如何传递?(2

14、)深入理解线程与进程的概念,在Windows环境下何时使用进程,何时使用线程?2.2实验二:线程的同步2.2.1 实验目的进一步掌握windows系统环境下线程的创建和撤销熟悉windows系统提供的线程同步API使用windows系统提供的线程同步API解决实际问题2.2.2 实验准备知识:相关API函数介绍2.2.21等待对象等待对象(wait fuctions)函数包括等待一个对象(WaitForSingleObject()和等待多对象(WaitForMultipleObject()两个API函数。等待一个对象WaitForMultipleObject()用于等待一个对象。他等待的对象可

15、以为以下对象之一。Change notification:变化通知。Console input:控制台输入。Events:事件。Job:作业。Mutex:互斥信号量。Process:进程。Semaphore:计数信号量。Thread:线程。Waitable timer:定时器。 原型:DWORD WaitForSingleObject(HANDLE hHandle, /对象句柄DWORD dwMilliseconds /等待时间);参数说明:hHandle:等待对象的对象句柄。该对象句柄必须为SYNCHRONIZE访问。dwMilliseconds:等待时间,单位为ms。若改值为0,函数在测试

16、对象的状态后立即返回,若为INFINITE,函数一直等待下去,直到收到一个信号将其唤醒,如表2-1所示。 返回值:如果返回成功,其返回值说明是何种事件导致函数返回。表2-1 函数描述 访问 描述WAIT_ABANDONED 等待对象的是一个互斥(mutex)对象,该互斥对象没有被拥有它的线程释放,他被设置为不能被唤醒WAIT_OBJECT_0 指定对象被唤醒WAIT_TIMEOUT 超时用法举例:Staitic HANDLE hHandle1=NULL;DWORD dRes;dRes=WaitForSingleObject(hHandle1, 10); /等待对象的句柄为hHandle,等待时

17、间为1000ms等待多个对象WaitForMultipleObject()在指定时间内等待多个对象,他等待的对象与WaitForSingleObject()相同。原型:DWORD WaitForMultipleObject(DWORD nCount, /句柄数组中的句柄数XONST HANDLE *lpHandles, /指向对象句柄数组的指针BOOL fWaitAll, /等待类型DWORD dwMilliseconds /等待时间);参数说明:nCount:由指针*lpHandles指定的句柄数组中的句柄数,最大数是MAXIMUM_WAIT_OBJECTS。*lpHandles:指向对象句

18、柄数组的指针。fWAitAll:等待类型。若存为true,当由lpHandles数组指定的所有对象被唤醒时函数返回;若为FALSE,当由lpHandles数组制定的某一个对象被唤醒时函数返回,且有返回值说明事由哪个对象引起的函数返回。dwMilliseconds :等待时间。单位为ms。若该值为0,函数测试对象的状态后立即返回;若为INFINITE,函数一直等待下去,直到收到一个信号将其唤醒。 返回值:如果成功返回,其返回值说明是何种事件导致函数返回。各参数的描述如表2-2所示。表2-2各参数描述 访问 描述WAIT_OBJECT_0 to (WAIT_OBJECT 若bWaitAll为TRU

19、E,返回值说明所有被等待的对象均被唤醒;若_0+nCount-1) bWaitAll为FALSE。返回值减去WAIT_OBJECT_0说明lpHandles数组下标指定的对象满足等待条件。如果调用时多个对象同时被唤醒,则取多个对象中最小的那个数组下标WAIT_ABANDONED_0 to 若bWaitAll为TRUE,返回值说明所有被等带的对象均被唤醒,并且(WIAT_ABANDONED-0+NcOUNT-1) 至少有一个对象是没有约束的互斥对象;若bWaitAll为FALSE,返回值减去WAIT_ABANDONED_0说明lpHandles数组下标指定的没有约束的互斥对象满足等待条件WAIT

20、_TIMNEOUT 超时且参数bWaitAll指定的条件不能满足信号量对象(semaphore)信号量对象(semaphore)包括创建信号量(CreateSemaphore()打开信号量OpenSemaphore()及增加信号量的值(ReleaseSemaphore()函数。创建信号量CreateSemaphore()用于创建一个信号量。原型:HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,/安全属性LONG lInitialCount, /信号量对象初始值LONG liMaximumCount, /信号量

21、最大值LPCTSTR lpName/信号量名);参数说明:lpSemaphoreAttributes:指定安全属性,为null是,信号量得到一个默认的安全描述符。lInitialCount:指定信号量对象的初始值。该值必须大于等于0,小于等于lMaximumCount 。当其值大于0是,信号量被唤醒。当该函数释放了一个等待该信号量的线程时,lInitialCount值减1,当调用函数ReleaseSemaphore()时,按其指定的数量加一个值。lMaximumCount:指出该信号量的最大值,该值必须大于0.lpName:给出该信号量的名字。返回值:信号量创建成功,将返回该型号量的句柄。如果

22、给出的信号量名是系统已经存在的信号量,将返回这个已经存在的信号量的句柄。如果失败,系统返回null,还可以调用函数GEtLastError()查询失败的原因。用法举例:Static HANDLE hHandle1=null;/创建一个信号量,其初值为0,最大值为5,信号量的名字为“SemphoreName1”hHnadle1= CreateSemaphore(NULL,SemphoreName1); 打开信号量OpenSemaphore()用于打开一个信号量。原型:HANDLEOpenSemaphore(DWORDdwDesidedAccess, /访问标志BOOL bInheritHandl

23、e, /继承标志 LPCTSTRlpNme /信号量名);参数说明:(1).dwDesiredAccess:指出打开后要对信号量进行何种访问,如表所示。表 2-3 访问状态访问 描述SEMAPHORE_ALL_ACCESS 可以进行任何对信号量的访问SEMPHORE_MODFIY_STATE 可以使用ReleaseSemaphore()修改信号量的值,使信号量的值成为可用状态SYNCHRONIZE 使用等待函数(wait functions),等待信号量成为可用状态(). bInheritHandle:指出返回的的信号量句柄是否可以继承。().lpName:给出信号量的名字返回值:信号量打开成

24、功,将返回信号量的句柄;如果失败,系统返回null,可以调用函数GetLastError()查询失败的原因。;用法举例:Static HANDLE hHandle1=null;/打开一个名为 ” SemphoreName1 ” 的信号量,之后可使用ReleaseSemaphore()函数增加信号量的值hHandle1=OpenSemaphore(SEMAPHORE_MOFDIFY_START,NULL, ” SemphoreName1” );3. 增加信号量的值ReleaseSemaphore()用于增加信号量的值。原型:BOOL ReleaseSemaphore(HANDLE hSemaph

25、ore, /信号量对象句柄LONG lReleaseCount, /信号量要增加数值LPLONG lpPreiousCount /信号量要增加数值地址);参数说明:(1).hSemaphore:创建或打开信号量时给出的信号量对象句柄。Windows NT中建议使用SEMAPHORE_MODIFY_STARTE访问属性打开该信号量。(2). lReleaseCount:信号量要增加数值。该值必须大于0。如果增加该值后大于信号创建时给出的lMaximumCount值,则增加操作失效,函数返回FALSE。(3). lpPreiousCount :接收信号量的一个32位的一个变量。若不需要接受该值,可

26、以指定为null。返回值: 如果成功,将返回一个非0值;如果失败,系统返回一个0,可以调用一个GetLastError()查询失败的原因。用法举例:Static HANDLE hHandle1=NULL;BOOL rc;rc= ReleaseSemaphore(hHandle1,1,NULL);/给信号量的值加1;2.2.3实验内容完成主子两个线程之间的同步,要求子线程先执行。在主线程中使用系统调用CreateThread()创建一个子线程。主线程创建一个子线程后进入阻塞状态,直到子线程运行完毕后唤醒主线程。2.2.4实验要求能正确使用等待对象、WaitForSingleObject()或Wa

27、itForMultipleObject(0及信号量对象CreateSemaphore()、OpenSemaphore()、ReleaseSemaphore()等系统调用,进一步理解线程的同步。2.2.5实验指导具体操作过程同本章实验一,在Microsoft visual C+6.0环境下建立一个MFC支持的控制台文件,编写C程序,在程序中使用CreateSemaphore(NULL,0,1,”SemaphoreName1”)创建一个名为“SemaphoreName1”的信号量,信号量的初始值为0,之后使用OpenSemaphore(SYNCHRONIZE|SEMAPHORE_MODIFY_ST

28、ARTE,NULL, ”SemaphoreName1)打开该信号量,这里访问标志使用“SYNCHRONIZE|SEMAPHORE_MODIFY_STARTE”,以便之后可以使用WaitForSingleObject()等待该信号量及使用ReleaseSemaphore()释放该信号量,然后创建一个子线程,主线程创建子线程后调用WaitForSingleObject(hHandle1,INFINITE),这里等待时间设置为INFINITE表示一直等待下去,直到该信号量被唤醒为止。子线程结束,调用ReleaseSemaphore(hHandle1,1,NULL)释放信号量,使信号量的值加1。2.2

29、.6实验总结实验完成了主、子线程的同步,主线程创建子线程后,主线程塞,让子线程先执行,等子线程执行完后,由子线程唤醒子线程。主子线程运行情况如图: 主、子线程的运行情况2.2.7 源程序2.2.7 源程序/ Semaphore.cpp : Defines the entry point for the console application./#include stdafx.h#include Semaphore.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ T

30、he one and only application objectCWinApp theApp;using namespace std;static HANDLE h1; /线程句柄static HANDLE hHandle1=NULL; /信号量句柄void func();int _tmain(int argc, TCHAR* argv, TCHAR* envp)int nRetCode = 0;DWORD dwThreadID1;DWORD dRes,err;hHandle1=CreateSemaphore(NULL,0,1,SemaphoreName1);/创建一个信号量if (hHa

31、ndle=NULL)printf(Semaphore Create!n);else printf(Semaphore Create Success!n);hHandle1=OpenSemaphore(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE,NULL,SemaphoreName1); /打开信号量if (hHanle1=NULL) printf(Semaphore Open Fail!n);else printf(Semaphore Open Success!n);h1=CreateThread(LPSECURITY_ATTRIBUTES)NULL,0,(LPTHR

32、EAD_START_ROUTINE)func,(KPVOID)NULL,0,&dwThreadID1); /创建子线程if (h1=NULL) prienf(Thread1 create Fail!n);else printf(Thread1 create Success!n);dRes=WaitForSingleObject(hHandle1,INFINITE); /主线程等待子线程结束err=GetLastError();printf(WaitForSingleObject err = %dn,err);if (dRes=WAIT_TIMEOUT) printf(TIMEOUT!dRes=

33、%dn,dRes);else if (dRes=WAIT_OBJECT_0) printf(WAIT_OBJECT!dRes=%dn,dRes);else if (dRes=WAIT_ABANDONED) printf(WAIT_ABANDONED!Dres=%dn,dRes);else printf(dRes =%dn,dRes);CloseHand(h1);CloseHandle(hHandle1);ExitThread(0);return nRetCode;void func()BOOL rc;DWORD err;Printf(Now In Thread!n);rc =ReleaseSe

34、maphore(hHandle1,1,NULL);err =GetLastError(); /子线程唤醒主线程printf(ReleaseSemaphore err=%dn,err);if(rc=0) printf(Semaphore Release Fail!n);else printf(Semaphore Release Success!rc= %dn,rc);2.2.8实验展望上面的程序完成了主、子两个线程执行先后顺序的同步关系,思考以下问题。如何实现多个线程的同步?若允许子线程执行多次后主线程再执行,又如何设置信号量的初值?实验三:线程的互斥2.3.1实验目的(1)熟练掌握Window

35、s系统环境下线程的创建与撤销。(2)熟悉Windows系统提供的线程互斥API。(3)使用Windows系统提供的线程互斥API解决实际问题。2.3.2 实验准备知识:相关API函数介绍2.3.2.1临界区对象临界区对象(CriticalSection)包括初始化临界区(InitializeCriticalSection()、进入临界区(EnterCriticalSection()、退出临界区(LeaveCriticalSection()及删除临界区(DeleteCriticalSection()灯API函数。初始化临界区InitializeCriticalSection()用于初始化临界区对

36、象。原型:VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection );参数说明:lpCriticalSection:指出临界区对象的地址。返回值:该函数没有返回值。用法举例:LPCRITCAL_SECTION hCriticalSection;CRITICAL_SECTION Critical;hCriticalSection=&Critical;InitializeCriticalSection(hCriticalSection);进入临界区EnterCriticalSection()等待进入临界区的权限,当获得

37、该权限后进入临界区。原型:VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);参数说明:lpCriticalSection:指出临界区对象的地址。返回值:该函数没有返回值。用法举例:LPCRITICAL_SECTION hCriticalSection;CRITICAL_SECTION Critical;hCriticalSection=&Critical;EnterCriticalSection(hCriticalSection);退出临界区LeaveCriticalSection()释放临界区的使用权限。原型:VO

38、ID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);参数说明:lpCriticalSection:指出临界区对象的地址。返回值:该函数没有返回值用法举例:LPCRITICAL_SECTION hCriticalSection;CRITICAL_SECTION Critical;hCriticalSection=&Critical;LeaveCriticalSection(hCriticalSection);删除临界区DeleteCriticalSection()删除与临界区有关的所有系统资源。原型:VOID DeleteC

39、riticalSection(LPCRITICAL_SECTION lpCriticalSection);参数说明:lpCriticalSection:指出临界区对象的地址。返回值:该函数没有返回值。用法举例:LPCRITICAL_SECTION hCriticalSection;CRITICAL_SECTION Critical;hCriticalSection=&Critical;DeleteCriticalSection(hCriticalSection);互斥对象互斥对象(Mutex)包括创建互斥对象(CreateMutex()、打开互斥对象(OpenMutex()及释放互斥对象(Re

40、leaseMutex()API函数。创建互斥对象CreateMutex(0用于创建一个互斥对象。原型:HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName);参数说明:lpMutexAttributes:指定安全属性,为NULL时,信号量得到一个,默认的安全描述符。bInitialOwner:指定初始的互斥对象。如果该值为TRUE并且互斥对象已经纯在,则调用线程获得互斥对象的所有权,否则调用线程不能获得互斥对象的所有权。想要知道互斥对象是否已经存在,参见返回值说明

41、。lpName:给出互斥对象的名字。返回值:互斥对象创建成功,将返回该互斥对象的句柄。如果给出的互斥对象是系统已经存在的互斥对象,将返回这个已存在互斥对象的句柄。如果失败,系统返回NULL,可以调用函数GetLastError()查询失败的原因。用法举例:static HANDLE hHandle1=NULL;/常见一个名为MutexName1的互斥对象hHandle1=CreateMutex(NULL,FALSE, MutexName1);打开互斥对象OpenMutex()用于打开一个互斥对象。原型:HANDLE OpenMutex(DWORD dwDesiredAccess,BOOL bI

42、nheritHandle,LPCTSTR lpName);参数说明:指明系统安全属性支持的对互斥对象所有可能的访问。如果系统安全属性不支持,则不能获得对互斥对象访问权。(1)dwDesireAccess:指出发开后要对互斥对象进行何种访问,具体描述如表2-4所示。 表 2-4 对互斥对象的访问种类 访问 描述 MUTEX_ALL_ACCESS 可以进行对任何互斥对象的访问 SYNCHRONIZE 使用等待函数 wait functions 等待互斥对象成为可用状态或使用 ReleaseMutex()释放使用权,从而获得互斥对象的使用权(2) bInheritHandle: 指出返回信号量的句柄是否可以继承。(3) IpName : 给出信号量的名字。返回值互斥对象打

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

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号