《2023年河北工业大学操作系统实验报告.pdf》由会员分享,可在线阅读,更多相关《2023年河北工业大学操作系统实验报告.pdf(74页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、操作系统实验指导书实验一进程控制与描述一 实验目的通过对Windows X P 编程,进一步熟悉操作系统的基本概念,较好地理解Window s X P 的结构。通过创建进程、观测正在运营的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解W i ndow s X P 进程的“一生”。二 实验环境硬件环境:计算机一台,局域网环境;软件环境:Windows XP,Visua 1 C+6.。专业版或公司版。三、实验内容和环节第一部分Window s编程Window s XP可以辨认的程序涉及控制台应用程序、GUI应用程序和服务应用程序。本实验中重要用到的是控制台应用程序和G U
2、I应用程序。1、简朴的控制台应用程序创建一个名为“H ei l o 的应用程序,在“开始”菜单中单击“程序”一“附件”-“记事本”命令,将程序键入记事本中,并把代码保存为1-1.c pp。程序1-1 Windows X P的GU I应用程序#i ncIude v o id ma i n()(S t d:c o u tMH el Io,Windows X P”CL 1-l.cpp运 营 1 1.EXE程序,运营结果是:(假如运营不成功,则也许的因素是什么?)水*C:Docuent s and Sett ra to r桌值hellowindows XPPress any key to con ti
3、n u e.2、GU I 应用程序W i ndows X P Prof e ssio n a 1下的G U I应用程序,使用Visual C+编译器创建一个 GUI应用程序,代码中涉及了 WinMa i n()方法,该方法GU I 类型的应用程序的标准入口点。在“开始”菜单中单击“程序”-“附件”-“记事本”命令,将程序键入记事本中,并把代码保存为1-2,cpp程序1-2 Windows X P的 GU I 应用程序/ms g box 项目#in c 1 ude /标准的 includ e/告诉连接器与涉及Me s sageBox A P I 函数的u s e r 3 2 库进行连接#p r
4、agma c o mment(Iib,4tuse r 32.lib )/这是个可以弹出信息框然后退出的筒单的应用程序in t AP I ENTRY W inMa in(HINSTANC E。/*h I nstance*/,HINSTANCEoo/*hPrev I n s tance*/,L P S T R T 1 p Cmd L in e */,int。/*n C md S how*/)::Mess a geBox(NUL L,。/没有父窗口4tHel 1 o,W i ndows 2023”,消息框中的文本“Greetings,一 /消息框标题MB.OK);。/其中只有一个OK按钮/返回0 以
5、便告知系统不进入消息循环retu r n(0);)也可以运用任何其他文本编辑器键入程序代码,假如这样,例如使用W O R D 来键入和编辑程序,则应当注意什么问题?保存时将文献保存为“.cpp”的 C+文献在“命令提醒符”窗口运营C L.E X E,产 生 1-2.EXE文献:C:CL 1-2.c p p在程序1-2的 G U I应用程序中,一方面需要Windows.h 头文献,以便获得传送给Wi n Main()和 Mess a g e Box()API函数的数据类型定义。接 着 的 p ra g m a 指令指示编译器/连接器找到User 3 2.L I B 库文献并将其与产生的EXE文献
6、连接起来。这样就可以运营简朴的命令行命令CL MsgBox.CPP来创建这一应用程序,假如没 有 pra g m a指令,则 M e s s a geBo x()AP I 函数就成为未定义的了。这一指令是Vis u alStud i o C+编译器特有的。接下来是WinMain()方法。其中有四个由实际的低档入口点传递来的参数。h Instan c e 参数用来装入与代码相连的图标或位图一类的资源,无论何时,都可用GetModuleHandleO A PI函数将这些资源提取出来。系统运用实例句柄来指明代码和初始的数据装在内存的何处。句柄的数值事实上是EX E文献映像的基地址,通常为0 x00
7、4 0 00 0 0 o 下一个参数hPrevInstanc e 是为向后兼容而设的,现在系统将其设为NULL。应用程序的命令行(不涉及程序的名称)是IpCmdL i n e参数。此外,系统运用nCmd Show参数告诉应用程序如何显示它的主窗口(选项涉及最小化、最大化和正常)。最后,程序调用M e ssageBox()AP I 函数并退出。假如在进入消息循环之前就结束运营的话,最后必须返回0。运营结果(试将其中的信息与程序1 -1 .E X E 的运营结果进行比较):弹出一个消息框,标题为G r e e tin g s,内容为H ello,W i n d o ws 202 3,中间有一个确认
8、按钮3、进程对象操作系统将当前运营的应用程序看作是进程对象。运用系统提供的惟一的称为句柄(HAN D L E)的号码,就可与进程对象交互。这一号码只对当前进程有效。本实验表达了一个简朴的进程句柄的应用。在系统中运营的任何进程都可调用G e tCunentProcessO API函数,此函数可返回标记进程自身的句柄。然后就可在W i ndows需要该进程的有关情况时,运用这一句柄来提供。程 序 1-3:获得和使用进程的句柄/prochan d 1 c 项目#in c 1 ude#i n c 1 ude/拟定自己的优先权的简朴应用程序v oid ma i n()(/从当前进程中提取句柄H ANDL
9、E h P roc e s s Thi s=:Ge t C urre n(Process();/请求内核提供该进程所属的优先权类DWORD dwPr i ority=:Get P r i orityCla s s(h P r ocessThis);/发出消息,为用户描述该类st d::c out “Curr e nt p ro c e s s p r ior i ty:;swi t c h(dwP r iority)(case HIGH_P R IORITY.C LAS S:std:co u t H i g h ;br e a k;case N 0 RM A L _ P RIORIT Y_CL
10、AS S:std::cout N o r mal”;br e ak;case I DLE_PRIORIT Y_CLASS:s t d:c o ut w“I d 1 e”:b reak;caseRE A L T I ME_PR10 RITY_CLASS:std::co u t ;br e a k;)s t d:c out std:endl;)程 序 1-3中列出的是一种获得进程句柄的方法。对于进程句柄可进行的惟一有用的操作是在A PI调用时,将其作为参数传送给系统,正如程序1-3 中对Get Pri o ri t y Cl a ss()API函数的调用那样。在这种情况下,系统向进程对象内“窥视”
11、,以决定其优先级,然后将此优先级返回给应用程序。Open P r oce s s()和 Cre a t e P ro c ess()API函数也可以用于提取进程句柄。前者提取的是已经存在的进程的句柄,而后者创建一个新进程,并将其句柄提供出来。在“命令提醒符”窗口运营C L.E X E,产 生 1-3.EXE文献:C:CL 1-3.c p p进程优先权为Normal将程序1 -4.cpp程序键入记事本中,并把代码保存为l-4.c p p。程 序 1-4显示如何找出系统中正在运营的所有进程,如何运用0 p enProc e ss()API函数来获得每一个访问进程的进一步信息。程序14运用句柄查出进
12、程的具体信息/proc 1 i s t 项目#include#in c lude#inc 1 ude/当在用户模式机内核模式下都提供所耗时间时,在内核模式下进行所耗时间的64位计算的帮助方法DWORD Get Ke r nelModeP e r centag e(co n st FILETIM E&ftKernel,co n s t F I LETIM E&ftUs e r)(/将FILET I M E结构转化为64位整数ULONGLONG q wK erne 1 =(ULONGL ONG)f t Kernel.dwHighDat e Tim e)32)+f t Ke r ne 1 .dwLo
13、w D a teTime;ULONGLONGqwUser=(ULONG LONG)f t U s er.dwHighDateTime)3 2)+f t User.dw Low Date T i me;/将消耗时间相加,然后计算消耗在内核模式下的时间比例ULONGLONG qwTotal=qwKe r n e 1 +qwUser;D WORD d w Pc t=(DWOR D)(ULO NG LONG)10 0*qwKe r nel)/q wTotal);r et u r n(dwP c t);)/以下是将当前运营进程名和消耗在内核模式下的时间百分数都显示出来的应用程序v o id main()
14、(/对当前系统中运营的进程拍取“快照”HANDLE h Snap s h ot=:C r eateToolh e p 3 2Snaps h ot(TH 3 2 C S-S NAPPROCESSW/提取当前进程0);。-/假如是当前进程,就将其忽略/初始化进程入口PROCESSENTRY32 pe;::Z eroMemory(&pe,siz e o f(p e);pe.dwS i z e=s izeof(p e);/按所有进程循环B OOL bMor e=:Pro cess 3 2First(hSn a psh o t,&p e);w h i 1 e(bMo r e)(/打开用于读取的进程HAN
15、DLE h Proc e ss=:O p en Proces s(P ROCESS_QUERY_ I NF O RM A T IO N,山 指明要得至 信息FALSE,。/不必继承这一句柄pe.t h 32 P roce s sID);/要打开的进程if(hP rocess!=NULL)/找出进程的时间F I LETIM E ftC r eat i o n,ftExi t,f t Kerne 1 Mode,ftUse r Mode;:Get P r o c ess T ime s(h Process,/所感爱好的进程&ftCrea t ion产。进程的启动时间(绝对的)&ftE x it,0
16、0 。/结束时间(假如有的话)&ftKe r ne 1 Mod e a/在内核模式下消耗的时间&ftUs e rMod e)产。/在用户模式下消耗的时间/计算内核模式消耗的时间比例D WORD dw P c t Kerne 1 =::G e t K e r nelM o dePerce n tage(f(KernelMode,。如在内核模式上消耗的时间f t UserMo d e);-。在用户模式下消耗的时间/向用户显示进程的某些信息s t d::cou t CL 1 -4.cpp运营结果:第二部分:进程的“一生”w i ndows所创建的每个进程都从调用C reate Process。A P
17、 I函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。每一进程都以调用Exi t Proce s s()或 T e rminatePro ce ss()A P I函数终止。通常应用程序的框架负责调用ExitProcess。函数。对于C+运营库来说,这一调用发生在应用程序的m a in()函数返回之后。1、创建子进程本实验显示了创建子进程的基本框架。该程序创建的子进程仍然执行父进程的程序代码,显示它的系统进程ID 和它在进程列表中的位置。创建子进程/proccreate 项目#incl u d ewindows.h#i n elude#include/创建传递过来的进程的克隆过程并赋于
18、其ID值v oid StartC 1 one(i n t nC 1 onelD)/提取用于当前可执行文献的文献名TCHA R szF i lcnameMAX_PA T H;::GetM o d u leFileN a me(N UL L,szF i len a me,M AX_ PATH);/格式化用于子进程的命令行并告知其EXE文献名和克隆IDTCHAR szCmdLine M A X _PA TH ;:s p rintf(sz C mdLine,%s%d,s zFil e n a me,nClonel D);/用于子进程的STARTUP IN FO结构STARTUPINFO si;::Z
19、e r o Memo r y(r einterp r et_ c ast (&s i),sizeof(si);si.c b=s i z eof(s i);。&/必须是本结构的大小/返回的用于子进程的进程信息P ROCE S SJN F O RMATION pi;/运用同样的可执行文献和命令行创建进程,并赋于其子进程的性质B OOL bCr e a t eOK=:Cr e a teProce s s(s z Filen a me,。产生这个E X E的应用程序的名称szCmdLine,-/告诉其行为像一个子进程的标志N U LL,。/缺省的进程安全性NUL L,g。缺省的线程安全性FALSE,。
20、/不继承句柄CREATE_NEW_CONSOLE,o/使用新的控制台N U LL-。/新的环境NULL,。当前目录&si,。/启动信息&p i);。“/返回的进程信息/对子进程释放引用i f(b C r eateO K)(:Clo s eHan d 1 e(pi.hP rocess):::C loseHa n dle(pi.hT h r e a d);Iint ma i n(i n t arg c,c har*argv)/拟定进程在列表中的位置int nCl o ne(0);if(arg c 1)/从第二个参数中提取克隆I D::s s c anf(argvl ,“%d,&n C 1 one)
21、;)/显示进程位置st d:c o ut Proc ess ID:44 :GetCurrentProc e ssl d()“,C 1 one I D:44 nCI o n e s t d::endl;/检查是否有创建子进程的需要c o n s t in t c_n C 1 oneMax=25;i f(nC 1 one C _n C Ion e Max)(/发送新进程的命令行和克隆号Star t Clo n e(+n Cion e);)/在终止之前暂停一下,输入一个字符后,程序结束,以便观测。S td:c ou t Vvinput a c h ar:“;get c h a r();s td:c
22、o m g one.Bye-b y e”;:Sleep(l 0(X);retu r n 0;本程序展示的是一个简朴的使用Crea t e P r o c e s s()A P I 函数的例子。一方面形成简朴的命令行,提供当前的E X E 文献的指定文献名和代表生成克隆进程的号码。大多数参数都可取缺省值,但是创建标志参数使用了:行为像一个子进程 标志,指示新进程分派它自己的控制台,这使得运营示例程序时,在任务栏上产生许多活动标记。然后该克隆进程的创建方法关闭传递过来的句柄并返回m a in()函数。在关闭程序之前,每一进程的执行主线程都会暂停等待输入字符,以便让用户观测子进程的行为。C reat
23、 e P r ocess()函数有5 个核心参数?本实验程序中设立的各个参数的值的含义是:a.(LPC T S T R 1 p Ap p licationName)szFilename,/产生这个 EXE 的应用程序的名称;b.(LPTST R 1 pC 0 mman d L i n e)s z CmdL i n e,/告诉其行为像一个子进程的标志;c.(B OOL blnheri t Handles)FALSE,不继承句柄;d.(LPSTARTGPINFOlpS t artupln f 0)&s i,/启动信息;e.(LPP ROCESS_INFOR MATION 1 pP r o c es
24、slnformat i on)&pi);/返回的进程信息程序运营时屏幕显示的信息是:Process ID:3344.Clone ID:0input a char:I 9m goneBye-byePress any key to continue2、正在运营的进程本实验的程序中列出了用于进程信息查询的API函数GetProce s s Versi o n()与 GetV e rsionEx()的共同作用,可拟定运营进程的操作系统的版本号。使用进程和操作系统的版本信息/v ers i on 项目#inc 1 ude#i nc 1 u d e /运用进程和操作系统的版本信息的简朴示例voi d ma
25、i n()(/提取这个进程的I D号DWORD dwIdTh i s=::G e tC u r re n tProce s sld();/获得这一进程和报告所需的版本,也可以发送。以便指明这一进程DWORD d wVerReq=:Get P roces s V ersion(d w Id T hi s);W 0 RD wM a j orRe q=(WORD)dwVerR e q 1 6);WO RDwM inorReq=(WORD)dwVerR e q&Oxf f f f);st d::cout v P r ocess I D:dwIdThis4t,r e qu i re s O S:44 w
26、 Ma j or Req wMino r Req s t d::endl;/设立版本信息的数据结构,以便保存操作系统的版本信息OSVERS I ON I NFOEX osvi x;::Ze r oMemory(&o s vix,sizeof(o s v ix);osvi x.dw 0 SV e r sion I n f o S iz e=s izeof(osvix);/提取版本信息和报告::G e t V e rsi o nEx(re interprct_c a s t (&o s vi x);std:cout Running on 0 S:“=5)(/改变优先级::S e t P r i o
27、r i tyCl a ss(:GetCu r ren t P r o c ess(),。运用这一进程HIGH_PRIORI T Y.C L A S S)/改变为 high/报告给用户std:cou t *4T a sk Ma n ager should now now ind i c at e th is”“process i s hig h pr i ority.M st d:endl;)Process ID:5436,requires OS:00Running on OS:5.1Task Manager should now now indicate thisprocess is high
28、 priority.Press any key to continue当前PI D信息:5 43 6当前操作系统版本:5.1系统提醒信息:Ta s k Man a g e r should now now i n di c ate t h i s proces s ishigh prio r ity程序向读者表白了如何获得当前的P I D 和所需的进程版本信息。为了运营这一程序,系统解决了所有的版本不兼容问题。接着,程序演示了如何使用GetVersionEx()A P I函数来提取OSVERSION I NFOEX结构。这一数据块中涉及了操作系统的版本信息。其中,O S:5.1”表达当前运营的
29、操作系统是:windows XP最后一段程序运用了操作系统的版本信息,以确认运营的是Wi n d ows X P。代码接着将当前进程的优先级提高到比正常级别高。单击C t r 1 +Alt+D el键,进 入“Windows任务管理器”,在“应用程序”选项卡中右键单击本任务,在快捷菜单中选择“转到进程”命令。在“Wind o w s 任务管理器”的“进程”选项卡中,与本任务相应的进程映像名称是(为什么?):VCSPAWN.EXE右键单击该进程名,在快捷菜单中选择“设立优先级”命令,可以调整该进程的优先级,如设立 为“高”后重新运营程序,屏幕显示有变化吗?没有3、终止进程指令其父进程来“杀掉”自
30、己的子进程/P rocte r m 项目#inclu d e#in c lud e#include static LPC T STR g _ s zMut e x Nam e=w2k d g.ProcT e rm.mutex.S uici d e”;/创建当前进程的克隆进程的简朴方法v o id S ta r t Cl o ne()(/提取当前可执行文献的文献名TCHA R szFi 1 ename MAX_PAT H ;:Ge t Modul e F i 1 e Name(NULL,szFil e n a me,MAX_PA T H);格式化用于子进程的命令行,指明它是一个E X E文献和子
31、进程TCHA R szCmdLin e M A X _ P A T H;;:s p ri n t f(szCmdLine,s child”,szFi 1 en a me);/子进程的启动信息结构STARTU PINFO si;:ZeroMem o r y(re i nte r pret_cast (&si),si z e o f(s i)si.cb=s i z eof(si);9 应当是此结构的大小/返回的用于子进程的进程信息PROCESSNFORM ATION pi;/用同样的可执行文献名和命令行创建进程,并指明它是一个子进程BOOL bC r e a teOK=:Cr e a t eP r
32、 oc e ss(szFilen a me,。产生的应用程序名称(本E X E文献)szCmdLine,。/告诉我们这是一个子进程的标志NULL,。用于进程的缺省的安全性NULL,-/用于线程的缺省安全性F A L S E,血/不继承句柄CR E ATE_NE W _CONS 0 LE,/创建新窗口,使输出更直观NULL,”。/新环境N U L L,。/当前目录&s i,。/启动信息结构&P i);/返回的进程信息/释放指向子进程的引用if(b Creat e OK)(:Clos e Handle(p i.hPr o c e s s);:CloseHandl e(p i.hTh r ead);
33、)void P a re nt()(/创 建“自杀”互斥程序体H A ND L E hM u texSuicide=::C r eat e Mutex(NULL产 。/缺省的安全性TRUE户。最初拥有的g_szMute x N am e):为其命名if(hMu te x S uicide!=NULL)(/创建子进程s t d:co u t 4tC r eating the c h ild p r o c ess.”st d:endl;:StartClone();/暂停:si e e p(500 0);/指令子进程“杀”掉自身st d::cou t 4 fcT e Hing the c h il
34、 d p r ocess to q uit.”s t d:endl;:ReleaseMut e x(hMu te x S u ic id e);/消除句柄::Clo s eHandle(hM u tex S uicid e);)void C hild()(/打 开“自杀”互斥体HAN DLE hMu t ex S u i c ide=::Open Mutex(SY N C H R O N IZE,/打开用于同步FALSE,。/不需要向下传递g_szMutexName);。/名称if (hMu t exSuicide!=NULL)/报告正在等待指令s t d:cout 1&:str c m p(
35、a r g v 1 ,“c hi 1 d)=0)(Child();)else(P a ren t();)ret u r n 0;I程序说明了一个进程从 生 到 死 的整个一生。第一次执行时,它创建一个子进程,其行为如同“父亲”。在创建子进程之前,先创建一个互斥的内核对象,其行为对于子进程来说,如同一个“自杀弹”。当创建子进程时,就打开了互斥体并在其他线程中进行别的解决工作,同时等待着父进程使用Re lease M u te x ()A PI发 出“死亡”信号。然后用S 1 e e P()API调用来模拟父进程解决其他工作,等完毕时,指令子进程终止。当调用Exit P ro cess。时耍小心,
36、进程中的所有线程都被立刻告知停止。在设计应用程序时,必须让主线程在正常的C+运营期关闭(这是由编译器提供的缺省行为)之后来调用这一函数。当它转向受信状态时,通常可创建一个每个活动线程都可等待和停止的终止事件。在正常的终止操作中,进程的每个工作线程都要终止,由主线程调用ExitProc ess()。接着,管理层对进程增长的所有对象释放引用,并 将 用 GetEx i tCod eProce s s()建立的退出代码从ST I LL_ACTIVE改变为在ExitP r oce s s()调用中返回的值。最后,主线程对象也如同进程对象同样转变为受信状态。等到所有打开的句柄都关闭之后,管理层的对象管理
37、器才销毁进程对象自身。还没有一种函数可取得终止后的进程对象为其参数,从而使其“复活”。当进程对象引用一个终止了的对象时,有好几个API函数仍然是有用的。进程可使用退出代码将终止方式告知给调用GetE x i tC odeP ro c e s s()的其他进程。同时,G e tPr o cessTim e s()A P I函数可向主调者显示进程的终止时间。C liilr l in g f-n i c i de i I H:L Ilu:I i ons.i n-4 t.hn c J(i d p r n i:;.:;.L._c -C:D ocu en t s a n d S ett i n gs A
38、d i n i stra a tur 桌面 D eb ug l.exe,C rea ti n g the chi l d process.T el l i n g the chi l d process to qui t.P ress a n y k ey to con ti n ue.1)_C renting t he ch i Id processChi 1 d waitin g fo r su i ci d e i ns t rue t i ons.表达:父进程正在创建子进程。子进程等待父进程杀死子进程。_2)_T e Hi n g t h e child proce s s to q
39、uit._表达:_ 父进程杀死子进程。_四 实验总结请总结一下本次实验的收获、教训和感受,结合课本内容谈一下你对进程的理解。本实验让我明白进程是程序的一次执行过程,是系统进行解决机调度和资源分派的基本单位。(未引入线程之前)。进程是操作系统结构的基础;是一个正在执行的程序;计算机中正在运营的程序实例;可以分派给解决器并由解决器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元实验二并发与调度一 实验目的在本实验中,通过对事件和互斥体对象的了解,来加深对W indows XP线程同步的理解。通过度析实验程序,了解管理事件对象的API。了解在进程中如何使用事件对
40、象,在进程中如何使用互斥体对象,线程如何通过文献映射对象发送数据。二 实验环境硬件环境:计算机一台,局域网环境;软件环境:Windows XP Pr o f e s s io n al,Visua 1 C+6.0 专业版或公司版。三、实验内容和环节第一部分:互斥体对象本程序中显示的类CC ou ntUpD o w n 使用了一个互斥体来保证对两个线程间单一数值的访问。每个线程都企图获得控制权来改变该数值,然后将该数值写入输出流中。创建者事实上创建的是互斥体对象,计数方法执行等待并释放,为的是共同使用互斥体所需的资源(因而也就是共享资源)。1、运用互斥体保护共享资源/mutex 项目#i n c
41、 1 u d e#i n c lude/运用互斥体来保护同时访问的共享资源cla s s CCountU p Down(publ i c:/创建者创建两个线程来访问共享值CC o u n tU p D o wn(int nAcc e ss e s):m.hThrca dine(INVALID_HAN D LE.VALU E),m_h Thre adDec(IN VALI D_H AN DLE_V A L UE),m_hMut e xValue(INV A L ID _H A N D LE_ VALUE),m_ nVa 1 u e(0),m_n A c c ess(n Accesses)(/创建
42、互斥体用于访问数值m_ hM u texV a lueCr e a t eM u t e x(NULL,/缺省的安全性TRU E,a/初始时拥有,在所有的初始化结束时将释放NULL);/匿名的m_hThread I nc=:Crea t eT h r e ad(NULL,。/缺省的安全性0,/缺省堆栈IncThreadP ro c ,/类线程进程r e in t e r p r e t_cas t (t his),/线程参数0,-/无特殊的标志NULL);,/忽略返回的idm_ h T h readD e c=::CreateThrea d(NULL-/缺省的安全性0,8/缺省堆栈DecThr
43、ea d P r o c,。/类线程进程reint e r p r et_ca s t (t his),g 线程参数0产 /无特殊的标志NULL):皿忽略返回的id/允许另一线程获得互斥体:R e leaseMutex(m_h M u tex Vai u e);)/解除程序释放对对象的引用v i r tual CCoun t UpD o w n()I:CloseHandle(m_hT h re a d in e);:CloseHan d le(mhThr e ad D ec);:Clos e H a ndle(m_hM u t e xV a lu e);)/简朴的等待方法,在两个线程终止之前可
44、暂停主调者vi r t u a 1 void W aitF o r Com p 1 e t i o n()/保证所有对象都已准备好if(m _hThread I nc!=I NV AL I D _H A N D LE_VALUE&m _hThreadDe c!=INVALID.HANDL E_VALUE)/等待两者完毕(顺序并不重要)::Wait F orSi n gle0 b j ec t(m_h Thr e a d I n c,IN FIN I TE);::WaitForSin g leOb j e c t(m_hTh r eadDec,I N F IN I T E);1)p rot e
45、ct e d:/改变共享资源的简朴的方法v irtu a I v o i d DoC o unt(i nt n S t e p)(/循环,直到所有的访问都结束为止while(m_n A cc e ss 0)(/等待访问数值::W a i tForSi n g 1 eObject(m_hMut e xValu e,IN F IN I T E);/改变并显示该值m_n V alue+=n S t e p;std:co u t th r ead:M :Get C urrentT h readld()v a lue:vV m_nvalue acces s:w m nAcc e ss s t d:cnd
46、l;/发出访问信号并允许线程切换-m_nAc c es s;:si e ep(IO 0 0);W/使显示速度放慢/释放对数值的访问:R e Ie a seM u tex(m_hMu t exV a lu e);)static DWORD WIN A P I I ncTh readProc(L PV O I D 1 p Param)(/将参数解释为this,指针CCoun t Up Down*pThi s=r ein t er p ret_c a s t (IpPa r am);/调用对象的增长方法并返回一个值pThi s-D o Count(+1);r e t ur n(0);st a tic
47、 DWOR D W I N APIDcc Threa d P r oc(LPVO I D 1 pParam)/将 参 数 解 释 为h i S,指针C Count U p D ow n*pT h i s=reint e r pr e t_ c ast (I p P a r a m);/调用对象的减少方法并返回一个值pThis-DOCount(-l);return(O);)p r otected:H A ND L E m_hThreadI n c;HANDLE m_hThread D ec;HANDLE m_hMute x V a lue;int m_ n Value;int m_nA c ce
48、s s;v o id m a in()(CCo u n t UpDown u d(5 0);ud.W a itForComp 1 eti o n();)分析程序的运营结果,可以看到线程(加和减线 程)的 交 替 执 行(由 于 Sleep()A PI允许Wi n d o w s 切换线程)。在每次运营之后,数值应当返回初始值(0),由于在每次运营之后写入线程在等待队列中变成最后一个,内核保证它在其他线程工作时不会再运营。1)请描述运营结果(假如运营不成功,则也许的因素是什么?):thread:302lvalue:laccess:26thread:5508ualue:Oaccess:25thre
49、ad:302lvalue:laccess:24thread:5500value:0access:23thread:3020ualue:laccess:22thread:5500ualue:Saccess:21thread:3028ualue:laccess:20thread:5500value:access:19thread:3020ualue:laccess:18thread:55O0ualue:access:1?thread:3020ualue:laccess:16thread:5500ualue:0access:15thread:3020value:laccess:14thread:55
50、00value:Saccess:13thread:3020value:laccess:12thread:5500value:Success:11thread:3028ualue:laccess:10thread:5500ualue:0access:9thread:302lvalue:laccess:8thread:5500value:0access:7thread:3028value:laccess:6thread:5508value:Saccess:5thread:3020ualue:laccess:4thread:5500ualue:Oaccess:3thread:3028ualue:la