实验三操作系统实验Nacho.docx
《实验三操作系统实验Nacho.docx》由会员分享,可在线阅读,更多相关《实验三操作系统实验Nacho.docx(14页珍藏版)》请在冰豆网上搜索。
![实验三操作系统实验Nacho.docx](https://file1.bdocx.com/fileroot1/2023-1/9/9a280bdd-0f93-4c0a-85d9-7840e0561f35/9a280bdd-0f93-4c0a-85d9-7840e0561f351.gif)
实验三操作系统实验Nacho
实验三操作系统实验Nacho
一、实验人员:
二、实验目的:
本次实验的目的在于掌握使用nachos中的线程序解决较为复杂的并发问题。
实验内容分三部分:
实现事件栅栏原语并进行正确性测试;实现闹钟原语并进行正确性测试;利用事件栅栏和闹钟原语来解决电梯问题(详细内容请看nachos-labs.pdf)。
三、实验内容:
1.实现事件栅栏原语
2.实现闹钟原语
3.解决电梯问题
四、实验步骤:
1.实现事件栅栏原语
EventBarrier.h
#ifndefEVENTBARRIER_H
#defineEVENTBARRIER_H
#include"synch-sem.h"
#defineSIGNALED1
#defineUNSIGNALED0
classEventBarrier{
public:
EventBarrier();
~EventBarrier();
voidWait();
voidSignal();
voidComplete();
intWaiters();
private:
boolstate;
Condition*waits;
Condition*waitc;
Lock*barrier;
Lock*inbarrier;
intwaiter;
};
#endif
EventBarrier.cc
#include"EventBarrier.h"
#include"thread.h"
EventBarrier:
:
EventBarrier()
{
waits=newCondition("waitsignal");
waitc=newCondition("waitcomplete");
barrier=newLock("barrier");
inbarrier=newLock("inbarrier");
state=UNSIGNALED;
waiter=0;
}
EventBarrier:
:
~EventBarrier()
{
deletewaits;
deletewaitc;
}
voidEventBarrier:
:
Wait()
{
barrier->Acquire();
waiter++;
while(state==UNSIGNALED)
waits->Wait(barrier);
barrier->Release();
}
voidEventBarrier:
:
Signal()
{
barrier->Acquire();
state=SIGNALED;
waits->Broadcast(barrier);
barrier->Release();
inbarrier->Acquire();
waitc->Wait(inbarrier);
inbarrier->Release();
state=UNSIGNALED;
}
voidEventBarrier:
:
Complete()
{
inbarrier->Acquire();
waiter--;
if(waiter==0)
{
waitc->Broadcast(inbarrier);
}
else
{
waitc->Wait(inbarrier);
}
inbarrier->Release();
}
intEventBarrier:
:
Waiters()
{
returnwaiter;
}
2.实现闹钟原语
Alarm.h
#ifndefALARM_H
#defineALARM_H
#include"system.h"
#include"list.h"
classAlarm{
public:
Alarm();
~Alarm();
voidPause(inthowLong);
voidWakeup();
intGetpausenum();
private:
List*queue;
intpausenum;
intleftime;
};
#endif
Alarm.cc
#include"system.h"
#include"thread.h"
#include"Alarm.h"
externAlarm*alarm;
voidcheck(intwhich)
{
while(alarm->Getpausenum()!
=0)
{
currentThread->Yield();
}
currentThread->Finish();
}
Alarm:
:
Alarm()
{
queue=newList();
pausenum=0;
}
Alarm:
:
~Alarm()
{
queue->~List();
}
voidAlarm:
:
Pause(inthowLong)
{
Thread*t;
pausenum++;
if(pausenum==1)
{
t=newThread("forkedthread");
t->Fork(check,0);
}
if(howLong<=0)
return;
leftime=stats->totalTicks+howLong*TimerTicks*10000;
IntStatusoldlevel=interrupt->SetLevel(IntOff);
queue->SortedInsert(currentThread,leftime);
currentThread->Sleep();
(void)interrupt->SetLevel(oldlevel);
}
voidAlarm:
:
Wakeup()
{
Thread*thread;
intptime=-1;
IntStatusoldLevel=interrupt->SetLevel(IntOff);
thread=(Thread*)queue->SortedRemove(&ptime);
(void)interrupt->SetLevel(oldLevel);
while(thread!
=NULL)
{
if(stats->totalTicks>=ptime)
{
scheduler->ReadyToRun(thread);
pausenum--;
oldLevel=interrupt->SetLevel(IntOff);
thread=(Thread*)queue->SortedRemove(&ptime);
(void)interrupt->SetLevel(oldLevel);
continue;
}
else
{
oldLevel=interrupt->SetLevel(IntOff);
queue->SortedInsert(thread,ptime);
(void)interrupt->SetLevel(oldLevel);
break;
}
}
}
int
Alarm:
:
Getpausenum()
{
returnpausenum;
}
3.实现单个电梯
Elevator.h
classElevator
{
public:
Elevator(char*debugname,intnumfloors,intmyid);
~Elevator();
char*getName(){returnname;}
voidOpenDoors();/*电梯开门*/
voidCloseDoors(inti);/*电梯关门*/
boolVisitFloor(intfloor);/*查看电梯是否访问某层*/
boolEnter(intid);/*乘客进入电梯*/
voidExit(intid);/*乘客离开电梯*/
voidRequestFloor(intfloor);/*乘客阻塞在电梯内部*/
intGetID(){returnid;}
intGetFloor(){returncurrentfloor;}
intGetState(){returnstates;}
voidSetState(inti);/*设置电梯状态*/
boolIFEMPTY();/*电梯是否为空*/
voidGoUp();/*电梯上行*/
voidGoDown();/*电梯下行*/
private:
char*name;
intid;
intnumFloors;/*电梯所能到达的最大楼层*/
intcurrentfloor;/*目前所在楼层*/
intoccupancy;/*目前乘客数目*/
intMaxNumber;/*最大乘客数目*/
intstates;/*电梯状态*/
EventBarrier*eventbarrier;/*电梯栅栏*/
bool*ifvisitfloor;/*判断电梯是否停留某楼层的数组*/
Lock*occlock;
};
classBuilding
{
public:
Building(char*debugname,intnumfloors,intnumelevators);
~Building();
char*getName(){returnname;}
voidCallUp(intfromFloor);
voidCallDown(intfromFloor);
Elevator*AwaitUp(intfromFloor);/*乘客等待,阻塞,返回电梯指针*/
Elevator*AwaitDown(intfromFloor);/*乘客等待,阻塞,返回电梯指针*/
boolGetDownLight(intfloor){returnDownLight[floor];}
boolGetUpLight(intfloor){returnUpLight[floor];}
voidSetDownLight(intt,booli);
voidSetUpLight(intt,booli);
voidWakeUp();
voidWakeDown();
Elevator*TellElevator();
private:
char*name;
intNumElevators;/*电梯数目*/
intNumFloors;/*楼层数目*/
EventBarrier*eventbarrier_up;/*上行栅栏*/
EventBarrier*eventbarrier_down;/*下行栅栏*/
Elevator*elevator;/*一个电梯*/
bool*DownLight;/*楼层下行按键*/
bool*UpLight;/*楼层上行按键*/
};
Elevator.cc
#include"synch-sleep.h"
#include"system.h"
#include"EventBarrier.h"
EventBarrier:
:
EventBarrier()
{
eventlock=newLock("eventlcok");
complete=newCondition("complete");
signal=newCondition("signal");
SIGNALED=false;
waiters_count=0;
}
EventBarrier:
:
~EventBarrier()
{
deleteeventlock;
deletesignal;
deletecomplete;
}
voidEventBarrier:
:
Wait()
{
eventlock->Acquire();
waiters_count++;
while(!
SIGNALED)/*如果事件栅状态是UNSIGNALED,则阻塞*/
signal->Wait(eventlock);
eventlock->Release();
}
voidEventBarrier:
:
Signal()
{
eventlock->Acquire();
SIGNALED=true;/*设置事件栅栏的状态为SIGNALED*/
//printf("\nsetSIGNALED=true,waitingforallforksWakeUp");
signal->Broadcast(eventlock);/*唤醒所有阻塞于Signal的线程*/
complete->Wait(eventlock);/*阻塞于Complete*/
//printf("\nhasalreadysignaledallwaitingforks");
SIGNALED=false;/*恢复事件栅栏的状态为UNSIGNALED*/
//printf("\nhasalreadyresetSIGNALED=false\n");
eventlock->Release();
}
voidEventBarrier:
:
Complete()
{
eventlock->Acquire();
waiters_count--;
if(waiters_count==0)/*最后一个应答,唤醒所有阻塞在complete的线程*/
complete->Broadcast(eventlock);
elseif(waiters_count>0)/*并非最后一个应答,阻塞在complete*/
complete->Wait(eventlock);
else
printf("\nwaiters_counterror!
");
eventlock->Release();
}
intEventBarrier:
:
Waiters()
{
returnwaiters_count;
}
五、实验结果
1.事件栅栏测试结果
2.闹钟测试结果
3.电梯测试结果
普通情况
电梯满
六、实验总结
本次实验关于电梯的程序难度较大,特别是电梯部分。
电梯部分只是初步实现了部分的功能,只有单部电梯且最多9个rider才能正常运转。
本次实验问题非常多,主要的有如下几点:
1.事件栅栏中要注意线程被唤醒时,返回wait时,要处于一个while循环中,否则可能造成信号丢失。
2.闹钟原语中,wait要在system.cc中的时间中断处理函数中调用。
3.最初写的电梯代码结果总是停在电梯开门的情况,后来参考了别人的代码发现许多变量需要加锁。
最终写出来的电梯还是比较脆弱的,只有在线程小于9的时候才可以正常运行,而且电梯满的时候有时候会有问题。