操作系统课程设计报告Word文档格式.docx
- 文档编号:6233937
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:23
- 大小:142.39KB
操作系统课程设计报告Word文档格式.docx
《操作系统课程设计报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计报告Word文档格式.docx(23页珍藏版)》请在冰点文库上搜索。
6
4.1.2.2、join()的源程序:
4.1.2.3、join()的测试用例及结果:
7
4.2、condition2():
4.2.1、condition2()的编程思想:
4.2.2、condition2()的源程序:
4.2.3、condition2()的测试用例及结果:
8
4.3、waitUntil():
9
4.3.1、waitUntil()的设计思想:
4.3.2、waitUntil()源程序:
4.3.3、waitUntil()的测试用例及结果:
10
4.4、speak(int)、listen():
11
4.4.1、speak(int)、listen()的设计思想:
4.4.2、speak(int)、listen()的源程序:
4.4.3、speak(int)、listen()的测试用例及结果:
12
4.5、:
priorityScheduler13
4.5.1、priorityScheduler的设计思想:
13
4.5.2、priorityScheduler的源程序:
4.5.3、priorityScheduler的测试用例及结果:
五、总结13
实现Nachos操作系统project1中的join(),condition2()、waitUntil()、speak(intword)和listen()函数以及priorityScheduler类。
熟悉nachos操作系统,深入理解操作系统内核。
三、实验要求:
完成nachosproject1,提交设计文档和你的代码(包括测试用例)。
四、实验说明、程序代码及测试结果
要求:
实现ImplementKThread.join()函数。
注意:
其它的线程不必调用join函数,但是如果它被调用的话,也只能被调用一次。
对join函数第二次调用的执行结果是不被定义的(即使第二次调用的线程与第一次调用的线程不同)。
(线程队列实现)
当A线程调用B.join()时,A线程阻塞,直到B线程完成。
在join()函数中,在A不为完成态时,将A放到阻塞队列中,并执行阻塞函数。
在finish()函数中,循环唤醒所有被阻塞的线程。
publicvoidjoin(){
Lib.debug(dbgThread,"
Joiningtothread:
"
+toString());
Lib.assertTrue(this!
=currentThread);
if(this.status!
=statusFinished)//如果当前进程不是完成态
{
booleanintstatus=Machine.interrupt().disable();
blockQueue.waitForAccess(currentThread);
//并把该线程放到阻塞队列中
KThread.sleep();
//使该进程休眠
Machine.interrupt().restore(intstatus);
}
}
publicstaticvoidfinish(){
Finishingthread:
currentThread.toString());
Machine.interrupt().disable();
Machine.autoGrader().finishingCurrentThread();
Lib.assertTrue(toBeDestroyed==null);
toBeDestroyed=currentThread;
currentThread.status=statusFinished;
KThreadnextThread=currentThread.blockQueue.nextThread();
while(nextThread!
=null)
{nextThread.ready();
nextThread=currentThread.blockQueue.nextThread();
sleep();
}
图1.1join()函数测试结果
(信号量实现)
在KThread中,我们主要完成了对join函数及finish函数的完善与扩充。
join函数是完成对多个进程需调用同一个进程之间的互斥问题。
为保证每次只有一个进程调用该进程,而且还得保证当第一个调用该进程的进程结束后可以将其它的阻塞进程得于唤醒,因此这需要一个链表来完成该进程的信号量的管理。
join函数中如果调用的进程已经完成则返回,如果未完成,则将定义一个信号量,并将该信号量加入到信号量链表中,并对waiter进行P操作。
相应的在finish函数中得对信号量链表中完成对信号量进程执行V操作,并从信号量链表中移除一个信号量记录。
4.1.2.1、join()的源程序:
=statusFinished)
图1.2join()函数测试结果
通过利用中断有效和无效所提供的原子性实现条件变量。
我们已经提供类似的例子用例实现信号量。
你要按此提供类似的条件变量的实现,不能直接利用信号量来实现(你可以使用lock,虽然它间接地调用了信号量)。
在你完成时要提供条件变量的两种实现方法。
你的第二种条件变量实现要放在nachos.threads.Condition2中。
Condition2的作用是实现对需要使用该条件资源的进程的管理,因此需要一个等待队列将在该条件资源上阻塞的进程存储起来,所以我们定义了一个ThreadQueue类的对象waitQueue。
sleep函数功能是将需要使用该条件资源下的当前进程阻塞,并将当前进程加入到等待队列中。
因此实现该函数的步骤如下:
首先执行关中断操作,然后再释放当前进程所加的锁,目的是为了能将当前进程加入到waitQueue中,然后将当前进程转为阻塞状态,再调用acquire函数来获取锁,最后再执行开中断操作。
wake函数的功能是将在该条件资源上阻塞的进程队列中取一个进程对其进行唤醒操作。
首先执行关中断操作,然后调用nextThread函数从等待队列中取第一个进程,如果无等待该条件资源的进程,则执行开中断操作,跳出该函数,否则就将该进程进行唤醒操作,最近执行开中断操作。
wakeAll函数的功能是将在该条件资源上阻塞的进程都唤醒,因此可通过在while循环中调用wake函数来实现。
但是前提是该当前进程得已经加锁,因此得通过调用Lib.asserTrue(conditionLock.isHeldByCurrentTread)函数来确保该条件成立。
packagenachos.threads;
importnachos.machine.*;
publicclassCondition2
publicCondition2(LockconditionLock){
this.conditionLock=conditionLock;
waitQueue=ThreadedKernel.scheduler.newThreadQueue(false);
publicvoidsleep(){
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
booleanintStatus=Machine.interrupt().disable();
//关中断
conditionLock.release();
//释放当前进程所加的锁
waitQueue.waitForAccess(KThread.currentThread());
//将当前的进程加入到等待队列中
KThread.currentThread().sleep();
//把当前的进程转为阻塞状态
conditionLock.acquire();
//获取锁
Machine.interrupt().restore(intStatus);
//开中断
publicvoidwake(){
//关中断
KThreadthread=waitQueue.nextThread();
//从等待队列中取一个线程
if(thread==null)//如果线程为空,则开中断
Machine.interrupt().restore(intStatus);
return;
thread.ready();
//否则使这个线程转为就绪状态
publicvoidwakeAll(){
while(waitQueue.!
=null)
{wake();
privateLockconditionLock;
privatestaticThreadQueuewaitQueue=null;
图2condition2()函数测试结果
通过实现waitUntil(intx)方法来完成Alarm类。
一个线程通过调用waitUntil函数来挂起它自己,直到now+x后才被唤醒。
在实时操作中,对线程是非常有用的,例如实现光标每秒的闪烁。
这里并不要求线程被唤醒后马上执行它,只是在它等待了指定时间后将它。
放入等待队列中。
不要通过产生任何附加的线程来实现waitUntil函数,你仅需要修改waitUntil函数和时间中断处理程序。
waitUntil函数并不仅限于一个线程使用,在任意时间,任意多的线程可以调用它来阻塞自己。
Alarm的作用是实现可对多个进程进行阻塞,并在规定的时间将进程唤醒,因此要存储多个进程的进程名及其唤醒时间,因此我们定义了一个ThreadTime类来存储单个进程的信息,属性分别为该进程名与其唤醒时间。
为了可存储多个进程的信息,并且对多个进程按唤醒时间进行排序,因此使用了TreeSet的对象Threadset来存储多个进程的信息并在ThreadTime类中实现了Comparable接口中的CompareTo函数。
waitUntil函数是进程可调用的函数,在该函数中需将各进程的进程名及唤醒时间保存起来。
因此该函数的实现步骤如下:
首先关中断,然后将创建一个ThreadTime类的对象来存储当前进程的信息,并加入到Threadset中,然后再开中断。
timerInterrupt函数是实现将阻塞队列中的进程在其唤醒时间将其唤醒。
为了实现能够对阻塞队列中的进程进行循环判断,因此需创建Iterator的一个对象,然后再利用Iterator的hasNext来对阻塞队列中的进程进行循环判断,如果该进程的唤醒时间大于当前时间,则对下一个进程进行判断,否则就将该进程唤醒,然后从阻塞队列中将其移除,再对下一个进程进行判断,最后将当前进程由运行状态转换成就绪状态,运行下一个进程。
importjava.util.*;
publicclassAlarm{
publicAlarm(){
Machine.timer().setInterruptHandler(newRunnable(){
publicvoidrun(){timerInterrupt();
});
}
//实现将阻塞队列中的进程在其唤醒时间将其唤醒
publicvoidtimerInterrupt()
IteratorThreadIterator=Threadset.iterator();
while(ThreadIterator.hasNext())
ThreadTimethreadtime=(ThreadTime)ThreadIterator.next();
if(threadtime.getwakeTime()>
Machine.timer().getTime())//如果该进程的唤醒时间大于当前时间
break;
//则对下一个进程进行判断
threadtime.getThread().ready();
//将该进程唤醒
ThreadIterator.remove();
//从阻塞队列中把它删除
KThread.currentThread().yield();
publicvoidwaitUntil(longx){
//关中断
longwakeTime=Machine.timer().getTime()+x;
ThreadTimethreadtime=newThreadTime();
//创建一个ThreadTime类对象。
来储存进程当前的信息
threadtime.setThread(KThread.currentThread());
threadtime.setwakeTime(wakeTime);
Threadset.add(threadtime);
//加入到Threadset中
//当前进程睡眠
Machine.interrupt().restore(intStatus);
publicclassThreadTimeimplementsComparable
{
privateKThreadthread;
privatelongwaketime;
publicKThreadgetThread()
returnthread;
publicvoidsetThread(KThreadthread)
this.thread=thread;
publiclonggetwakeTime()
returnwaketime;
publicvoidsetwakeTime(longwaketime)
this.waketime=waketime;
publicintcompareTo(Objectp)
{
longtime=((ThreadTime)p).getwakeTime();
if(this.getwakeTime()<
time)
return-1;
if(this.waketime==time)
return0;
else
return1;
privatestaticSet<
ThreadTime>
Threadset=newTreeSet<
();
//用来存储多个进程的信息
图3waiUntil()函数测试结果
使用条件变量来实现一个字长信息的发送和接收同步。
使用voidspeak(intword)和intlisten()函数来实现通讯(Communicator)类的通讯操作。
speak函数具有原子性,在相同地Communicator类中等待listen函数被调用,然后将此字发生给listen函数。
一旦传送完毕,两个函数都返回(listen函数返回此字)。
注释:
你的解决方案要满足使用同一个通讯对象实例中多个speaker和listener能够相互通讯。
(注意:
这种情况等于0字长的缓冲区;
既然缓冲区没用空间,那么需要生产者和消费者直接进行交互,要求它们相互地等待)。
每一个通讯实例只能使用一个lock类。
如果你使用多于一个lock类的话,那么你会将事情复杂化。
在此题中,speak一个word,listen接收一个word,并返回。
他们是一对一操作。
听、说互斥,我们设了两个条件变量s,l,分别代表说和听,又因为他们成对出现,我们设了一个信号量r,初始化count=0,在speak函数中,当count=0时,执行speak操作,并使count+1,此时先阻塞speak,唤醒listen,阻塞r;
在listen函数中,当count=1时,执行listen操作,并使count-1,此时先阻塞listen,唤醒speak,唤醒r;
importjava.util.LinkedList;
publicclassCommunicator
publicLockmutex;
publicConditions;
//说
publicConditionl;
//听
intcount;
privateintword;
privateSemaphorer=newSemaphore(0);
//设置一个信号量
privateLinkedList<
Integer>
wdQueue;
publicCommunicator()
{
this.mutex=newLock();
this.s=newCondition(this.mutex);
this.l=newCondition(this.mutex);
count=0;
wdQueue=newLinkedList<
//定义一个链表实例,里面存放整型数组
}
publicvoidspeak(intword)
this.mutex.acquire();
//当前对象获取锁
if(count==0)
wdQueue.add(word);
count=count+1;
this.word=word;
this.s.sleep();
this.l.wake();
r.P();
else{
this.s.sleep();
this.mutex.release();
publicintlisten(){
intmess;
if(count==1)
wdQueue.remove();
count=count-1;
else
this.l.sleep();
this.s.wake();
mess=word;
r.V();
//释放锁
returnmess;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计 报告