北科大操作系统实验报告.docx
- 文档编号:3360330
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:23
- 大小:405.84KB
北科大操作系统实验报告.docx
《北科大操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《北科大操作系统实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
北科大操作系统实验报告
操作系统实验报告
学院:
计算机与通信工程学院
专业:
计算机与科学技术
班级:
学号:
姓名:
指导教师:
王成耀
成绩:
2015年1月4日
实验一线程的状态和转换(5分)
1实验目的和要求
目的:
熟悉线程的状态及其转换,理解线程状态转换与线程调度的关系。
要求:
(1)跟踪调试EOS线程在各种状态间的转换过程,分析EOS中线程状态及其转换的相关源代码;
(2)修改EOS的源代码,为线程增加挂起状态。
2完成的实验内容
2.1EOS线程状态转换过程的跟踪与源代码分析
(分析EOS中线程状态及其转换的核心源代码,说明EOS定义的线程状态以及状态转换的实现方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等)
//使Zero状态或者运行状态的线程转入就绪状态
VOID
PspReadyThread(
PTHREADThread
)
{
ASSERT(NULL!
=Thread);
ASSERT(Zero==Thread->State||Running==Thread->State);
//将线程插入其优先级对应的就绪队列的队尾,并设置就绪位图中对应的位。
//最后将线程的状态修改为就绪状态。
ListInsertTail(&PspReadyListHeads[Thread->Priority],&Thread->StateListEntry);
BIT_SET(PspReadyBitmap,Thread->Priority);
Thread->State=Ready;
}
//取消线程的就绪状态,使线程转入Zero状态
VOID
PspUnreadyThread(
PTHREADThread
)
{
ASSERT(NULL!
=Thread&&Ready==Thread->State);
//将线程从所在的就绪队列中取出,如果线程优先级对应的就绪队列变为空,
//则清除就绪位图中对应的位。
ListRemoveEntry(&Thread->StateListEntry);
if(ListIsEmpty(&PspReadyListHeads[Thread->Priority])){
BIT_CLEAR(PspReadyBitmap,Thread->Priority);
}
Thread->State=Zero;
}
//使处于等待状态的线程脱离等待队列并转入Zero状态
VOID
PspUnwaitThread(
INPTHREADThread
)
{
ASSERT(Waiting==Thread->State);
//将线程从所在等待队列中移除并修改状态码为Zero。
ListRemoveEntry(&Thread->StateListEntry);
Thread->State=Zero;
//如果线程注册了等待计时器,则注销等待计时器。
if(STATUS_TIMEOUT==Thread->WaitStatus){
KeUnregisterTimer(&Thread->WaitTimer);
}
}
2.2为线程增加挂起状态的实现
(给出实现方法的简要描述、源代码、测试和结果等)
{
STATUSStatus;
BOOLIntState;
THREADThread;
//根据线程句柄获得线程对象的指针
Status=ObRefObjectByHandle(hThread,sThreadTye,(VOID*)&Thread);
if(EOS_SUCCESS(Status)){
IntState=KeEnableInterruts(FALSE);//关中断
if(Zero==Thread->State){
ListRemoveEntry(&Thread->StateListEntry);
sReadyThread(Thread);
sThreadSchedule();
Status=STATUS_SUCCESS;
}else{
Status=STATUS_NOT_SUORTED;
}
KeEnableInterruts(IntState);//开中断
ObDerefObject(Thread);
}
returnStatus;
}
3其他需要说明的问题
//线程调度
VOID
PspThreadSchedule(
VOID
)
{
ULONGHighestPriority;
//注意,如果当前正在处理中断(中断嵌套深度不为0)则什么也不做,
//因为在中断返回时系统会自动执行线程调度。
if(KeGetIntNesting()==0){
if(Running!
=PspCurrentThread->State){
//当前线程已经处于非运行状态,执行线程调度。
KeThreadSchedule();
}elseif(0!
=PspReadyBitmap){
//扫描就绪位图,如果存在比当前线程优先级高的就绪线程则执行线程调度。
BitScanReverse(&HighestPriority,PspReadyBitmap);
if(HighestPriority>PspCurrentThread->Priority)
KeThreadSchedule();
}
}}
实验二进程的同步(7分)
1实验目的和要求
目的:
理解进程同步的原理和意义,掌握信号量的实现方法和应用。
要求:
(1)使用EOS的信号量,实现生产者-消费者问题;
(2)跟踪调试EOS信号量的工作过程,分析EOS信号量实现的源代码;
(3)修改EOS信号量的实现代码,使之支持等待超时唤醒和批量释放功能。
2完成的实验内容
2.1使用EOS的信号量实现生产者-消费者问题
(简要说明使用EOS的信号量解决生产者-消费者问题的实现方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪、测试与思考等)
//创建生产者线程。
//
ProducerHandle=CreateThread(0,//默认堆栈大小
Producer,//线程函数入口地址
NULL,//线程函数参数
0,//创建标志
NULL);//线程ID
if(NULL==ProducerHandle){
return4;
}
//创建消费者线程。
ConsumerHandle=CreateThread(0,
Consumer,
NULL,
0,
NULL);
if(NULL==ConsumerHandle){
return5;
}
//生产者线程函数。
ULONGProducer(PVOIDParam)
{
inti;
intInIndex=0;
for(i=0;i WaitForSingleObject(EmptySemaphoreHandle,INFINITE); WaitForSingleObject(MutexHandle,INFINITE); printf("Producea%d\n",i); Buffer[InIndex]=i; InIndex=(InIndex+1)%BUFFER_SIZE; ReleaseMutex(MutexHandle); ReleaseSemaphore(FullSemaphoreHandle,1,NULL); //休息一会。 每500毫秒生产一个数。 Sleep(500); } return0; } //消费者线程函数。 ULONGConsumer(PVOIDParam) { inti; intOutIndex=0; for(i=0;i WaitForSingleObject(FullSemaphoreHandle,INFINITE); WaitForSingleObject(MutexHandle,INFINITE); printf("\t\t\tConsumea%d\n",Buffer[OutIndex]); OutIndex=(OutIndex+1)%BUFFER_SIZE; ReleaseMutex(MutexHandle); ReleaseSemaphore(EmptySemaphoreHandle,1,NULL); //休息一会儿。 让前10个数的消费速度比较慢,后面的较快。 if(i<10){ Sleep(2000); }else{ Sleep(100); } } return0; } 2.2EOS信号量工作过程的跟踪与源代码分析 (分析EOS信号量实现的核心源代码,简要阐述其实现方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等) //信号量的Wait操作(P操作)。 { BOOLIntState; STATUSflag; ASSERT(KeGetIntNesting()==0);//中断环境下不能调用此函数。 IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。 //目前仅实现了标准记录型信号量,不支持超时唤醒功能,所以PspWait函数 //的第二个参数的值只能是INFINITE。 if(Semaphore->Count>0){ Semaphore->Count--; flag=STATUS_SUCCESS; } else flag=PspWait(&Semaphore->WaitListHead,Milliseconds); KeEnableInterrupts(IntState);//原子操作完成,恢复中断。 returnflag; } //信号量的Signal操作(V操作) { STATUSStatus; BOOLIntState; IntState=KeEnableInterrupts(FALSE);//开始原子操作,禁止中断。 if(Semaphore->Count+ReleaseCount>Semaphore->MaximumCount){ Status=STATUS_SEMAPHORE_LIMIT_EXCEEDED; }else{ //记录当前的信号量的值。 if(NULL! =PreviousCount){ *PreviousCount=Semaphore->Count;} intval=Semaphore->Count; //目前仅实现了标准记录型信号量,每执行一次信号量的释放操作 //只能使信号量的值增加1。 while((! ListIsEmpty(&Semaphore->WaitListHead))&&(ReleaseCount)){ PspWakeThread(&Semaphore->WaitListHead,STATUS_SUCCESS); PspThreadSchedule(); ReleaseCount--; } Semaphore->Count=val+ReleaseCount; //可能有线程被唤醒,执行线程调度。 Status=STATUS_SUCCESS; } KeEnableInterrupts(IntState);//原子操作完成,恢复中断。 returnStatus; } 2.3支持等待超时唤醒和批量释放功能的EOS信号量实现 (给出实现方法的简要描述、源代码、测试和结果等) { BOOLIntState; STATUSflag; ASSERT(KeGetIntNesting()==0);//中断环境下不能调用此函数。 IntState=KeEnableInterruts(FALSE);//开始原子操作,禁止中断。 //目前仅实现了标准记录型信号量,不支持超时唤醒功能,所以sWait函数 //的第二个参数的值只能是INFINITE。 if(Semahore->Count>0){ Semahore->Count--; flag=STATUS_SUCCESS; } else flag=sWait(&Semahore->WaitListHead,Milliseconds); KeEnableInterruts(IntState);//原子操作完成,恢复中断。 returnflag; } 实验三时间片轮转调度(5分) 1实验目的和要求 目的: 理解进程(线程)调度的执行时机和过程,掌握调度程序实现的基本方法。 要求: (1)跟踪调试EOS的线程调度程序,分析EOS基于优先级的抢占式调度的源代码; (2)修改EOS的调度程序,添加时间片轮转调度。 2完成的实验内容 2.1EOS基于优先级的抢占式调度工作过程的跟踪与源代码分析 (分析EOS基于优先级的抢占式调度的核心源代码,简要阐述其实现方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等) //选择优先级最高的非空就绪队列的队首线程作为当前运行线程。 PspCurrentThread=CONTAINING_RECORD(PspReadyListHeads[HighestPriority].Next,THREAD,StateListEntry); ObRefObject(PspCurrentThread); PspUnreadyThread(PspCurrentThread); PspCurrentThread->State=Running; 2.2为EOS添加时间片轮转调度的实现 (给出实现方法的简要描述、源代码、测试和结果等) { //判断被中断进程是否仍处于运行状态 if(NULL! =sCurrentThread&&Running==sCurrentThread->State){ //被中断进程的时间片减少1 sCurrentThread->RemainderTicks--; //判断被中断线程的剩余时间片是否等于0 if(sCurrentThread->RemainderTicks==0){ //重新为被中断线程分配时间片 sCurrentThread->RemainderTicks=TICKS_OF_TIME_SLICE; //是否存在和被中断线程优先级相同的就绪进程 if(BIT_TEST(sReadyBitma,sCurrentThread->riority)){ //将被中断线程转入就绪状态,并插入对应就绪队列的末尾 sReadyThread(sCurrentThread);} } } return; } 运行结果: 3其他需要说明的问题 //内核中关于线程四种状态的转换规定 //线程的四种状态: 就绪(Ready)、运行(Running)、等待(Waiting)和结束(Terminated)。 //注意: Zero不是线程的有效状态,是一种游离状态,是线程状态转换的中间态。 tyedefenum_THREAD_STATE{ Zero,//0 Ready,//1 Running,//2 Waiting,//3 Terminated//4 }THREAD_STATE; VOID sReadyThread( THREADThread ) { ASSERT(NULL! =Thread); ASSERT(Zero==Thread->State||Running==Thread->State); // //将线程插入其优先级对应的就绪队列的队尾,并设置就绪位图中对应的位。 //最后将线程的状态修改为就绪状态。 // ListInsertTail(&sReadyListHeads[Thread->riority],&Thread->StateListEntry); BIT_SET(sReadyBitma,Thread->riority); 实验四物理存储器与进程逻辑地址空间的管理(1分) 1实验目的和要求 目的: 理解物理存储器以及进程逻辑地址空间的管理方法。 要求: (1)通过查看物理存储器的使用情况,练习物理内存的分配与回收,分析相关源代码,从而理解EOS物理存储器的管理方法; (2)通过查看进程逻辑地址空间的使用情况,练习虚拟内存的分配与回收,分析相关源代码,从而理解EOS进程逻辑地址空间的管理方法。 2完成的实验内容 2.1EOS物理内存分配和回收的练习以及源代码分析 (练习物理内存的分配和回收;分析相关源代码,简要说明EOS中物理存储器的管理方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等) //分配一个物理页 // MiAllocateAnyPages(1,PfnArray); fprintf(StdHandle,"\n******AfterAllocateOnePage******\n"); fprintf(StdHandle,"ZeroedPageCount: %d.\n",MiZeroedPageCount); fprintf(StdHandle,"FreePageCount: %d.\n",MiFreePageCount); fprintf(StdHandle,"UsedPageCount: %d.\n",MiTotalPageFrameCount-MiZeroedPageCount-MiFreePageCount); //然后再释放这个物理页 // MiFreePages(1,PfnArray); fprintf(StdHandle,"\n******AfterFreeOnePage******\n"); fprintf(StdHandle,"ZeroedPageCount: %d.\n",MiZeroedPageCount); fprintf(StdHandle,"FreePageCount: %d.\n",MiFreePageCount); fprintf(StdHandle,"UsedPageCount: %d.\n",MiTotalPageFrameCount-MiZeroedPageCount-MiFreePageCount); KeEnableInterrupts(IntState);//开中断 } 2.2EOS进程逻辑地址空间分配和回收的练习以及源代码分析 (练习虚拟内存的分配和回收;分析相关源代码,简要说明EOS中进程逻辑地址空间的管理方法;在应用进程中分配虚拟页和释放虚拟页的源代码、测试和结果等;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等) INT*d; if(d=VirtualAlloc(0,sizeof(int),MEM_RESERVE|MEM_COMMIT)) //调用API函数VirtualAlloc,分配一个整型变量所需的空间,并使用一个整型变量的指针指向这个空间。 { printf("Allocated%dbytesvirtualmemoryof0x%x\n\n",sizeof(int),d); printf("virtualmemoryoriginalvalue: 0x%x\n\n",*d);//输出原始整型变量的值 *d=0xFFFFFFFF;//修改整型变量的值为0xFFFFFFFF printf("virtualmemorynewvalue: 0x%x\n\n",*d);//输出修改后的整型变量的值 printf("\nWaitfor10seconds\n"); Sleep(10000);//调用API函数Sleep,等待10秒钟。 系统以毫秒为单位 if(VirtualFree(d,0,MEM_RELEASE))//调用API函数VirtualFree,释放之前分配的整型变量的空间 printf("\nRealeasevirtualmemorysuccess! \n"); else printf("realeaseerror\n"); printf("\nEndlessloop! "); for(;;){} //进入死循环,这样应用程序就不会结束 } else{ printf("error\n"); return-1;//若不能成功,打印error,并返回-1。 } //printf("Helloworld! \n"); return0; } 3其他需要说明的问题 //内核文件中关于函数变量的不同值会对地址空间进行不同方式的分配 STATUS MiReserveAddressRegion( INPMMVAD_LISTVadList, INPVOIDBaseAddress, INSIZE_TRegionSize, OUTPMMVAD*Vad ) { PLIST_ENTRYListEntry; PMMVADPointerVad; ULONG_PTRStartingVpn; ULONG_PTREndVpn; ULONG_PTRSize; ASSERT(RegionSize! =0&&BaseAddress+RegionSize-1>=BaseAddress); if(NULL! =BaseAddress){ StartingVpn=MI_VA_TO_VPN(BaseAddress); EndV
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北科大 操作系统 实验 报告