StackAllocate(func,arg);
oldLevel=interrupt->SetLevel(IntOff);
scheduler->ReadyToRun(this);//ReadyToRunassumesthatinterrupts
//aredisabled!
(void)interrupt->SetLevel(oldLevel);
++numOfThreads;
}
//---------------------------------------------------------------------
//Thread:
:
setExTime
//settheexecuteTimeofthethreadtoexT
//---------------------------------------------------------------------
void
Thread:
:
setExTime(intexT){
executeTime=exT;
}
//---------------------------------------------------------------------
//Thread:
:
setPriority
//setthepriorityofthethreadtopri
//---------------------------------------------------------------------
void
Thread:
:
setPriority(intpri)
{
priority=pri;
}
//---------------------------------------------------------------------
//Thread:
:
Priority
//returnthepriorityofthethread
//---------------------------------------------------------------------
int
Thread:
:
Priority(){
returnpriority;
}
//---------------------------------------------------------------------
//Thread:
:
setPriority
//setthetimeofthethreadtot
//---------------------------------------------------------------------
void
Thread:
:
setTime(intt){
time=t;
}
//---------------------------------------------------------------------
//Thread:
:
Time
//returnthetimeofthethreadneedtorun
//---------------------------------------------------------------------
int
Thread:
:
Time(){
returntime;
}
并在SimpleThread()中进行了如下修改:
staticvoid
SimpleThread(intwhich)
{
if(numOfThreads<128){
for(inti=0;i<(kernel->currentThread->Time())-(kernel->currentThread->executeTime)+2;i++){
cout<<"***thread"<currentThread->executeTime<<"times.\n";
cout<<"priority"<currentThread->Priority()<<"\n";
kernel->currentThread->Yield();
}
}
else{
if(count==0)
printf("Thenumberofthethreadscannotbelargerthan128!
\n");
kernel->currentThread->Yield();
count++;
}
}
对Scheduler.cc中进行了以下修改,实现了按照优先级进行线程的调度,返回最高优先级的线程,让其运行。
Thread*
Scheduler:
:
FindNextToRun()
{
ASSERT(kernel->interrupt->getLevel()==IntOff);
if(readyList->IsEmpty()){
returnNULL;
}else
{
Thread*highestPri=readyList->RemoveFront();
for(inti=1;iNumInList();i++){
if(readyList->IsEmpty()){
returnhighestPri;
}
if(readyList->Front()->Priority()<=highestPri->Priority()){
readyList->Append(highestPri);
highestPri=readyList->RemoveFront();;
}
}
returnhighestPri;
}
}
并在Run()中进行了以下修改:
在Run()代码的最后加了以下语句:
kernel->currentThread->setPriority(kernel->currentThread->Priority()+1);
kernel->currentThread->setExTime(kernel->currentThread->executeTime+1);
实验结果和结论:
对实验进行的测试,首先编译通过测试:
经过编译测试,程序已完成了以上要求,具体测试如下:
对遵循“优先级调度”抢占式调度的实现:
void
Thread:
:
SelfTest()
{
DEBUG(dbgThread,"EnteringThread:
:
SelfTest");
for(inti=0;i<=3;i++){
Thread*t=newThread("forkedthread");
t->setPriority(3-i);
t->Fork((VoidFunctionPtr)SimpleThread,(void*)numOfThreads);
}
}
对最多只有128个用户线程存在的实现:
参考文献:
实验项目三
实验项目名称:
Nachos中的文件管理系统
实验项目目的:
•实现多个线程同时存在内存,虚拟地址到物理地址的转换,限制程序大小,不实现缺页中断处理
•不实用虚拟内存
•维护二类页表
–实页页表(空闲页表):
操作系统维护
(Machine中创建)——nachos现在有多少页表是可以供用户使用
–线程页表:
各线程维护自己的页表
参与人员及分工:
乔心轲,何赵平,康小芳完成主要代码编写;
崔蓉,张文进行程序的测试及维护。
实验环境:
⏹Nachos:
NotAnotherCompletelyHeuristicOperatingSystem
⏹Linux
⏹Gcc
⏹Windows
实验内容:
首先是在Machine.h中对空闲页表及其相关函数进行了声明:
TranslationEntry*freePageTable;//空闲页表
TranslationEntryNextFreePage();//下一个空闲的页
intNumOfFreePage();//剩余空闲页的数目
其次在Machine.cc中空闲页表进行初始化以及函数的实现:
Machine:
:
Machine(booldebug)
{
inti;
for(i=0;iregisters[i]=0;
mainMemory=newchar[MemorySize];
for(i=0;imainMemory[i]=0;
freePageTable=newTranslationEntry[NumPhysPages];
for(i=0;ifreePageTable[i].virtualPage=i;
freePageTable[i].physicalPage=i;
freePageTable[i].valid=TRUE;
freePageTable[i].use=FALSE;
freePageTable[i].dirty=FALSE;
freePageTable[i].readOnly=FALSE;
}
#ifdefUSE_TLB
tlb=newTranslationEntry[TLBSize];
for(i=0;itlb[i].valid=FALSE;
pageTable=NULL;
#else//uselinearpagetable
tlb=NULL;
pageTable=NULL;
#endif
singleStep=debug;
CheckEndian();
}
//----------------------------------------------------------------------
//Machine:
:
NextFreePage()
//----------------------------------------------------------------------
TranslationEntry
Machine:
:
NextFreePage(){
for(inti=0;i{
if(freePageTable[i].valid==TRUE)
returnfreePageTable[i];
}
}
//----------------------------------------------------------------------
//Machine:
:
numOfFreePage()
//----------------------------------------------------------------------
int
Machine:
:
NumOfFreePage(){
intnum=0;
for(inti=0;i{
if(freePageTable[i].valid==TRUE)
num++;
}
returnnum;
}
对AddrSpace.cc的修改如下:
AddrSpace:
:
AddrSpace()
{
}
AddrSpace:
:
~AddrSpace()
{
if(pageTable!
=NULL){
for(inti=0;ipageTable[i].valid=TRUE;
pageTable[i].use=FALSE;
pageTable[i].dirty=FALSE;
pageTable[i].readOnly=FALSE;
}
deletepageTable;
}
}
为了实现限制程序大小以及实现线程页表和空闲页表的转换,对代码进行了如下修改:
bool
AddrSpace:
:
Load(char*fileName)
{
OpenFile*executable=kernel->fileSystem->Open(fileName);
NoffHeadernoffH;
unsignedintsize;
if(executable==NULL){
cerr<<"Unabletoopenfile"<returnFALSE;
}
executable->ReadAt((char*)&noffH,sizeof(noffH),0);
if((noffH.noffMagic!
=NOFFMAGIC)&&
(WordToHost(noffH.noffMagic)==NOFFMAGIC))
SwapHeader(&noffH);
ASSERT(noffH.noffMagic==NOFFMAGIC);
#ifdefRDATA
//howbigisaddressspace?
size=noffH.code.size+noffH.readonlyData.size+noffH.initData.size+
noffH.uninitData.size+UserStackSize;
//weneedtoincreasethesize
//toleaveroomforthestack
#else
//howbigisaddressspace?
size=noffH.code.size+noffH.initData.size+noffH.uninitData.size
+UserStackSize;//weneedtoincreasethesize
//toleaveroomforthestack
#endif
numPages=divRoundUp(size,PageSize);
size=numPages*PageSize;
ASSERT(numPages<=NumPhysPages);//checkwe'renottrying
//torunanythingtoobig--
//atleastuntilwehave
//virtualmemory
DEBUG(dbgAddr,"Initializingaddressspace:
"<pageTable=newTranslationEntry[numPages];
if(kernel->machine->NumOfFreePage()>=numPages){
for(inti=0;iTranslationEntrytemp=kernel->machine->NextFreePage();
pageTable[i].virtualPage=temp.virtualPage;
pageTable[i].physicalPage=temp.physicalPage;