操作系统实验五_第1页
操作系统实验五_第2页
操作系统实验五_第3页
操作系统实验五_第4页
操作系统实验五_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

、T众操作系统丫—,丫实验报告课程名称操作系统实验实验项目名称操作系统实验报告物理存储器与进程逻辑地址空间的管理学号2011班级姓名型钢专业学生所在学院指导教师实验室名称地点哈尔滨工程大学一、实验概述实验名称进程的同步实验目的使用EOS的信号量,编程解决生产者一消费者问题,理解进程同步的意义。调试跟踪EOS信号量的工作过程,理解进程同步的原理。修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。实验类型验证二、实验环境OSLab三、实验过程3.1准备实验按照下面的步骤准备本次实验:启动OSLab。新建一个EOSKernel项目。生成EOSKernel项目,从而在该项目文件夹中生成SDK文件夹。新建一个EOS应用程序项目。使用在第3步生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。3.2使用EOS的信号量解决生产者一消费者问题按照下面的步骤查看生产者一消费者同步执行的过程:使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件内的源代码。按F7生成修改后的EOS应用程序项目。按F5启动调试。OSLab会首先弹出一个调试异常对话框。在调试异常对话框中选择“否”,继续执行。立即激活虚拟机窗口查看生产者一消费者同步执行的过程。

待应用程序执行完毕后,结束此次调试。3.3调试EOS信号量的工作过程3.3.1创建信号量按照下面的步骤调试信号量创建的过程:按F5启动调试EOS应用项目。OSLab会首先弹出一个调试异常对话框。在调试异常对话框中选择〃是",调试会中断。在main函数中创建Empty信号量的代码行(第77行)EmptySemaphoreHandle=CreateSemaphore(BUFFER_SIZE,BUFFER_SIZE,NULL);添加一个断点。//LSTJMi略Li野.yIPT!十*々、由』丁[|£1丁工由』丁|心:?.、工&IZI和IH|ld|毕tEnptySemapharcHandlc=CreatcScrraphcrc(BUFF£E^_S12E^NULL),if(NULLkEmptySemaphoreHandle)(return2;按F5继续调试,到此断点处中断。按F11调试进入CreateSemaphore函数。可以看到此API函数只是调用了EOS内核中的PsCreateSemaphoreObject函数来创建信号量对象。按F11调试进入semaphore.c文件中的PsCreateSemaphoreObject函数。在此函数中,会在EOS内核管理的内存中创建一个信号量对象(分配一块内存),而初始化信号量对象中各个成员的操作是在PsInitializeSemaphore函数中完成的。在semaphore.c文件的顶部查找到PsInitializeSemaphore函数的定义(第19行),在此函数的第一行(第39行)代码处添加一个断点。留早(9跄|ASSERT(Ini1ialCount>=0&&InitialCount<-HaxiiuunCount&&■MaxiimunCount>0);41;Semaphore->Count=InitialCocnt;8.按F5继续调试,到断点处中断。观察PsInitializeSemaphore函数中用来初始化信号量结构体成员的值,应该和传入CreateSemaphore函数的参数值是一致的。9.按F10单步调试PsInitializeSemaphore函数执行的过程,查看信号量结构体被初始化的过程。打开〃调用堆栈〃窗口,查看函数的调用层次。ASSERT(InitialCount>=0MInitialCount<=HaxinujiCount£&laxinuroCoufit>0);中4140码4445474849SO51525354Seroaphore-Xount=InitialComt;Seiwhore->IaxiiDU£iCount=laxlmuffCoimt.ListlnitializeHead(fi:SeiDaphore->WaitListHead);STATUSPsWaitForSemaphore(INPSEIAPWRESeirophorEINULONGMilliseconds)功能描逑=循号量的Wait操作(P操作).Pilidtitlie*Smkj>lur«^hi903£btfD?I<iNFxpOE£r«<t«S«««^h4r«Gbj«ct成』.峥hcr«0bject=4z60^隹《•由,CretlcF*ObCr«*t«OI>j(Obj*ctTn>«=0N803fcO88,DbjtctHM*=OxD,Obj*ctB»dFxCr«el«S«««E4i4rvO^j*CtQnatiim■vCQ«it=0x«,IfipCr«a.tQniti*lCoun.t=Oxa,Ru:i■wCount^Oxia,Mm«=0x0^出“M3书«rgi:qwsi为地址MG#虹戒kVL"%—\iW"』PA旧鼻VWMJ*jQKr“t«0bj・H懒占序fQ*陌舞佻xu#埔■力成FxCrtkltStBtfiihortO'bjtcttLiuimiiCQ皿Cr**.!-«£«•a^aiitl*JLCdunl=QK■ut^wuifbUffil^OxHn<Ln.(Hr(c=l>KL^德址如⑩顿耻盘三虹出3睨占[二调阴雄我j有151字KeEn!ibleInterr^pt.sUntSt-ate),i"±jIbO1511史153项1施156157158回UL0NGObCetObjectId(INPVOIDObjectreturn.STATUSSUCCESS,Li瘩祖■PM词用增整名稀落%曲』时.哗口银矛!..芋昵|葛1SS瓶JStiatus-ObCreateHandle(SeuraphoreObject,SeiwhoreHancifStiatus-ObCreateHandle(SeuraphoreObject,SeiwhoreHancif('EOS_SUCCESS(Status))(returnSlatus;r-____,zm寸sgt-co由寸sgOOO'OO-■&Of=MhMi=<Ir=ff=M寸寸寸寸寸寸寸寸寸寸寸寸寸力寸PsSetLastError(Jr^nslateStatusToError(Status));}return£OS_S(KX3.SS(Status)?Handle:NULL.EOSAPIBOOLRt1easeSemaohore(INJttNDLEHandle,ItiLONGReleaseCaunt,,INPLONGPreviouECountSTATUSStatus;Vt?xas用汜疆tfliX名稀B«Ln.(u-«c!=QKLKrMDiqWMQ)凰址:皿网0捉莅字】~Ttvilic...3.3.2等待、释放信号量3.3.2.1等待信号量(不阻塞)生产者和消费者刚开始执行时,用来放产品的缓冲区都是空的,所以生产者在第一次调用WaitForSingleObject函数等待Empty信号量时,应该不需要阻塞就可以立即返回。按照下面的步骤调试:删除所有的断点(防止有些断点影响后面的调试)。在eosapp.c文件的Producer函数中,等待Empty信号量的代码行(144)WaitForSingleObject(EmptySemaphoreHandle,INFINITE);添加一个断点。143•1如14BbJ6147143•1如14BbJ614714814?15015L1剑printf(*Protiucea%d\n'"FL);InIndex]=i,

Inlndri=(Inlndfir+1)*BUFFER_SJZE;RjEleasEtfutex(MuleKKaji-dle);ReleaseSemfphore(Ful1SenHfphoreHandleFLNULL);-0X通用坞在TQX名稀值<乎此睛.IA姗脚(」酬行N4字】tns按F5继续调试,到断点处中断。WaitForSingleObject函数最终会调用内核中的PsWaitForSemaphore函数完成等待操作。所以,在semaphore.c文件中PsWaitForSemaphore函数的第一行(第68行)添加一个断点。按F5继续调试,到断点处中断。按F10单步调试,直到完成PsWaitForSemaphore函数中的所有操作。可以看到此次执行并没有进行等待,只是将Empty信号量的计数减少了1(由10变为了9)就返回了。如图所示,empty的初始值为10。67i06S'IASSERT(.IeGe11ntNestins()=0);//中折环慎下不能偶用』d70IntStaie-KeEnablelmtrruots(FALSE).//开橱原孑操作.71|////目前蚁实现了指演记枭型信号量,不支捋超时咀雀励能,F//的第二个签熟的值只能是INFINITE。//76iSeMphore-iCQunt―;*诣出T0X名稀待制作软遂镜像…正在启动VirtualPC■八开始调试…「<_由*^^^1,>■1<>仙珂,土扣以石七此1引监我D墟出二*.二部小『・•「S68字】g在完成PsWaitForSemaphore函数中的所有操作后empty的值变成了9。3.3.2.2释放信号量(不唤醒)删除所有的断点(防止有些断点影响后面的调试)。在eosapp.c文件的Producer函数中,释放Full信号量的代码行(第152行)ReleaseSemaphore(FullSemaphoreHandle,1,NULL);添加一个断点。按F5继续调试,到断点处中断。按F11调试进入ReleaseSemaphore函数。继续按F11调试进入PsReleaseSemaphoreObject函数。先使用F10单步调试,当黄色箭头指向第269行时使用F11单步调试,进入PsReleaseSemaphore函数。按F10单步调试,直到完成PsReleaseSemaphore函数中的所有操作。可以看到此次执行没有唤醒其它线程(因为此时没有线程在Full信号量上被阻塞),只是将Full信号量的计数增加了1(由0变为了1)。full信号量初始值为0lUOt107:甲I10S婿111IL13iW115lUOt107:甲I10S婿111IL13iW115lie117申据120121】跄申123:1IntStale=KeBnaiblelnterrvpt3(FALSE);/'/尸迷原工'.斐作.if(Senjaphare-^CDimt#ReleaseCount>SeiiHph-ore-1^aileStatus二STATUS_SEIAPHOKEXIMIKEXCEEDED.]&lse([记筑当前的馆号量廓恒,if(NULL1=PrevicusCaunt)(*PreviousCount=Sen>®hore-X?ountrS«*tptiorirXfl,nn.t0一询出眼,,心』汕"•STATUSStatus;BOOLIntState.制作软鱼镜队..正在启动VirtualPC-开始调试•…♦eaiwpF-Ttvtli®full信号量由0变为1aecraphore-X;ount+f;if(Semaphore"X^ount<=0)(PspWsk岸T旧建一冲对tListHe^d,STATUS}n//可能•有迷程袱哽酸,执行线程调度.//PspThrcadSchedule(),Status=STATUS^SimSS,KeEnisblrlnterruptsdntState)p//恢典中&JE丧FpX府出,4X名稀S调试-工,成吧Sv*tphor1刺僧软壑镜傣…4正在启动VirtualPC…开始调试….V《;|>♦时相imi戏加槌可£3监说三游出JJ诞点$3训用地状fj131T1tns生产者线程通过等待Empty信号量使空缓冲区数量减少了1,通过释放Full信号量使满缓冲区数量增加了1,这样就表示生产者线程生产了一个产品并占用了一个缓冲区。3.3.2.3等待信号量(阻塞)由于开始时生产者线程生产产品的速度较快,而消费者线程消费产品的速度较慢,所以当缓冲池中所有的缓冲区

都被产品占用时,生产者在生产新的产品时就会被阻塞,下面调试这种情况。结束之前的调试。删除所有的断点。按F5重新启动调试。OSLab会首先弹出一个调试异常对话框。在调试异常对话框中选择"是”,调试会中断。在semaphore.c文件中的PsWaitForSemaphore函数的PspWait(&Semaphore->WaitListHead,INFINITE);代码行(第78行)添加一个断点。了T申if(Setra(phore->CaurLt<0){J7SFspffait(aS«iHiphart->fljntLLstEfea^INFINITE);7^-)SOv-v-T—-//[Ksfr-Hr*rhd按F5继续调试,并立即激活虚拟机窗口查看输出。开始时生产者、消费者都不会被信号量阻塞,同步执行段时间后才在断点处中断。中断后,查看"调用堆栈”窗口,有Producer函数对应的堆栈帧,说明此次调用是从生产者线程函数进入的。在“调用堆栈”窗口中双击Producer函数所在的堆栈帧,绿色箭头指向等待Empty信号量的代码行,查看Producer函数中变量i的值为14,表示生产者线程正在尝试生产14号产品。for(i=0;i<PRODUCT.COUNT;i++)tReleaseMutProducer函数中变量i的值为14,表示生产者线程正在尝试生产14号产品。for(i=0;i<PRODUCT.COUNT;i++)tReleaseMutex(HutexHandle),辎匝13断菱]@调用增栈printf("Produce&%dWLi);Buffer[Inlndex]二i;InIndex=(InIndex+1)%BUFFER_SIZE;ObVtitForObjtct(Mtndle=0x5,Mi11iMcon4s=4294967295)...V»itForSincleObject0Undle=Ox5,Millis«conds=42^49672..■Producer(Far«n=0x0)■0x00401e69FspThretdStertupOiftijt0x80017•HO地址0x00000000任调试信息)WaitForSingleubject(EnptySemaphoreHandle,INFINITEWaitForSingleObject(JlutexHandle,INFINITE);Sleep(500),在“调用堆栈”窗口中双击PsWaitForSemaphore函数的堆栈帧,查看Empty信号量计数(Semaphore->Count)的值为-1,所以会调用PspWait函数将生产者线程放入Empty信号量的等待队列中进行等待(让出CPU)。

叫77】7S7S30S1S2S38485S687888990919293SoiwhQfre->Cgunt■■jif(Semaphore-XZount<0){]PspWait(fiSemaphore->WaitListHead,INFINITE);KcEnableInierruf>ts(IntState);//原子操作完成.恢复中目)returnSTATUS^SyOCESS;STATUSPsReleaseSensphere(INPSEIAPHORESeroaphoreaINLONGReleaseCount,OUTPLONGPreviousCount]/*++也▼?X调用地挟■PX名耕谊名称沁呻新•■心gl-1.砧峙hwtSt*峙h"虾。咎阿孔*垣「Uiilli«*C-4h43T.if'orO'bjcctQH.Kndl«=OtK5pUiHix.«.Freduc«iro-«»=0x£l)地位:口1<0>4皿姑FwpThr董■dSlurtup0地址:。xSOOIdh升°地址Qx^OOOOQW(SffiMffi.ft)<>,q查找皓果1'寻查魅-"监徂tsMUH]13聒点]*3蟹噂行78字1激活虚拟机窗口查看输出的结果。生产了从0到13的14个产品,但是只消费了从0到3的4个产品,所以缓冲池中的10个缓冲区就都被占用了,这与之前调试的结果是一致的。3.3.2.4释放信号量(唤醒)只有当消费者线程从缓冲池中消费了一个产品,从而产生一个空缓冲区后,生产者线程才会被唤醒并继续生产14号产品。可以按照下面的步骤调试:删除所有断点。在eosapp.c文件的Consumer函数中,释放Empty信号量的代码行(第180)ReleaseSemaphore(EmptySemaphoreHandle,1,NULL);添加一个断点。▲*y1791801S21"3Re1easelut由(KutexHandlie);Re1easeSemaphore(EmptySeroaphoreHandle#LNULL),//〃休息一会儿.II前10个数的消费速度比较慢.后面白按F5▲*y1791801S21"3Re1easelut由(KutexHandlie);Re1easeSemaphore(EmptySeroaphoreHandle#LNULL),//〃休息一会儿.II前10个数的消费速度比较慢.后面白按F5继续调试,到断点处中断。查看Consumer函数中变量i的值为4,说明已经消费了4号产品。按照3.3.2.2中的方法使用F10和F11调试进入PsReleaseSemaphore函数。查看PsReleaseSemaphore函数中Empty信号量计数(Semaphore->Count)的值为-1,和生产者线程被阻塞时的值是一致的。110.〜111

112113t?Ill11511&;11T申118119:120131122中123Iduuliniaiate,IntState=KeEnablelmm-upts(FALSE).产盐原子挽'克if(SeiDaphore^>Count+ReleaseCount>Sensaphsre^^Iazingx131!早if(Semaphore-Xount<=0)I中132PspWakeThread(ASemaphore->WaitListHead^STATUS133!:!134:135://1361//可能有线程被唤醒,执行线程调度,13辛//13母PspThreadSchedule();139=140!Status二STATUS-SUCCESS;14L-}142!143iKeEnableInterrupts(IntState);//原子操作完成,恢复中£0>监视▼以X调用雌栈名地值名称Seisaphorf)Couat0|中PsReleaseSemaphore(SeA&phcEsRtl«ts+S10ReleaEeSetnaphoreQtandlK(hConsumer(Param=OKO)地址FspThr1ttxtup0地址:Ch??0地址:0»00000000伏设按照下面的步骤验证生产者线程被唤醒后,是从之前被阻塞时的状态继续执行的:在semaphore.c文件中PsWaitForSemaphore函数的最后一行(第83行)代码处添加一个断点。按F5继续调试,在断点处中断。查看PsWaitForSemaphore函数中Empty信号量计数(Semaphore->Count)的值为0,和生产者线程被唤醒时的值是一致的。4.在“调用堆栈”窗口中可以看到是由Producer函数进入的。激活Producer函数的堆栈帧,查看Producer函数中变量i的值为14,表明之前被阻塞的、正在尝试生产14号产品的生产者线程已经从PspWait函数返回并继续执行了。5.结束此次调试。3.4修改EOS的信号量算法修改处代码434445464743妈5051it(.LJejnaphore-XJount>UJtSe^aphore-^Count■■jIfla8=STAnJS:_SUCCESS;fla®=PspWait(fibSeinaphiore-^aitHslHead,Hi11Iseconds)KeEnab1eInterrtsflntState);//原子操作完成,恢复中断中returnflag;while(11ListIsEmpty(&Semapbore->WaitListHead)(ReleaseCount))[PspWakerhreadC&Semaphore-^aitLisiHead,STATUS_SUCCESS);PspThreadSchedule(),ReleaseCount——,)|运行成功77:I//i匚童m刖佝站专重的值好if(NULL1=PreviousCounl)njvI___.—fl__OSLabPC-licrasoEtVirtualPC20D7|C0f6D^E-i(PressCtrl+Fi^F^tusuitchcghsdIewindow-…)

ConsumeaZ2Troducea23ConsumeaZ3jConsunerwaitforFullsenaphoretineoutiPrpdiicc«24ConsumeaZ4;iConsuneruaitforrullsenaphoretineoiLtProduceaZ5Consumea25tonsiinerwaitforfullseiwpliDretineoutJ*rt>dijictd26ConsumeaZ6ponsLineruaitforfill]senaphoretineoiut[Produceh27ConsumeaZ7ponsiiHeruaitforfullseriaphor«tineoutProduceaZBConsumeaZ8tonsuneruaitforFullsefkiphoretineoutProduce日Z9Consumea23H:\EOSApp.exeexituith0x00600006.3.4.3测试方法修改完毕后,可以按照下面的方法进行测试:使用修改完毕的EOSKernel项目生成完全版本的SDK文件夹,并覆盖之前的生产者一消费者应用程序项目的SDK文件夹。按F5调试执行原有的生产者一消费者应用程序项目,结果必须仍然与图13-2一致。如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,并重复步骤1。将Producer函数中等待Empty信号量的代码行WaitForSingleObject(EmptySemaphoreHandle,INFINITE);替换为while(WAIT_TIMEOUT==WaitForSingleObject(EmptySemaphoreHandle,300)){printf("Producerwaitforemptysemaphoretimeout\n〃);}将Consumer函数中等待Full信号量的代码行WaitForSingleObject(FullSemaphoreHandle,INFINITE);替换为while(WAIT_TIMEOUT==WaitForSingleObject(FullSemaphoreHandle,300)){printf("Consumerwaitforfullsemaphoretimeout\n〃);}启动调试新的生产者一消费者项目,查看在虚拟机中输出的结果,验证信号量超时等待功能是否能够正常执行。如果有错误,可以调试内核代码来查找错误,然后在内核项目中修改,并重复步骤1。如果超时等待功能已经能够正常执行,可以考虑将消费者线程修改为一次消费两个产品,来测试ReleaseCount参数是否能够正常使用。使用实验文件夹中NewConsumer.c文件中的Consumer函数替换原有的Consumer函数。四、思考题思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?可以参考本书第2章中的第2.6节。答:等待和释放操作都是原语操作,在执行等待信号量和释放信号量的时候,不能被打断,所以cpu是不允许响应外部中断的,如果此时cpu响应了外部中断,中间的某些共用的变量会产生不可预料的变化,无法正常完正常的操作。绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。(1)PsWaitForSemaphore

(2)PsReleaseSemaphoreIntState=KeEnablelnterrupts(FALSE);YesStatus=STATUS_SEMAPHORE_LIMIT_EXCEEDEDPspSchedule();Status=STATUSSUCCESSSemaphore->Count+ReleaseCou

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论