操作系统课程设计实验报告proj1.docx





《操作系统课程设计实验报告proj1.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计实验报告proj1.docx(25页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、操作系统课程设计报告操作系统课程设计报告班级:班级:团队成员团队成员:目录目录.2一、Nachos 综述.错误!未定义书签。错误!未定义书签。二、实验要求:建立线程系统.错误!未定义书签。错误!未定义书签。2.1 Task 1.1 实现 KThread.join().32.1.1 题目要求.32.1.2 题目分析与实现方案.32.1.3 关键点与难点.42.1.4 实现代码.42.2 Task 1.2 实现条件变量.52.2.1 题目要求.52.2.2 题目分析与实现方案.52.2.3 关键点与难点.62.2.4 实现代码.72.3 Task 1.3 完成 Alarm 类.72.3.1 题目要
2、求.72.3.2 题目分析与实现方案.82.3.3 关键点与难点.92.3.4 实现代码.92.4 Task 1.4 条件变量实现同步消息.102.4.1 题目要求.102.4.2 题目分析与实现方案.102.4.3 关键点与难点.112.4.4 实现代码.112.5 Task 1.5 实现优先级调度.132.5.1 题目要求.132.5.2 题目分析与实现方案.132.5.3 关键点与难点.142.5.4 实现代码.152.6 Task 1.6 条件变量解决过河问题.162.6.1 题目要求.162.6.2 题目分析与实现方案.172.6.3 关键点与难点.192.6.4 实现代码.19三、
3、测试结果.2 错误!未定义书签。错误!未定义书签。一、一、Nachos 综述综述Nachos 是一款教学用的操作系统平台,他的全名叫做“Not Another Completely Heuristic Operating System”,Nachos 的运行必须借助于宿主机,它通过软件模拟了各种硬件系统,包括中断系统、存储系统、磁盘文件、网络等。它的运行是可以跟踪的,因此,我们可以一步一步的观察操作系统是如何运行的。Nachos操作系统本身只提供了一套框架,很多地方的实现都需要我们自己来完善,因此我们可以通过修改其源代码,来丰富和增强Nachos 操作系统的功能.更可以在完善这些功能的同时,了
4、解操作系统的内部运行机制。二、实验要求:建立线程系统二、实验要求:建立线程系统2.12.1 TaskTask 1.11.1:实现:实现 KThread.join()KThread.join()2.11 题目要求实现 Implement Kthread.join()函数。其它的线程不必调用 join 函数,但是如果 join()函数被调用的话,也只能被调用一次。对 join()函数第二次调用的执行结果是不被定义的,即使第二次调用的线程与第一次调用的线程不同。无论有没有被 join,一个进程都能够正常结束。2.1.2 题目分析与实现方案分析:join 函数的作用即为等待调用此函数线程运行完毕。当前
5、线程 A 调用另一个线程(处于就绪状态)B 的 join 函数时,即 A 执行B.join()时(A和B在Nachos中均为Kthread类型对象),A被挂起,直到B 运行结束后,join 函数返回,A 才能继续运行。如果这个线程已经结束,马上返回。且 join()函数只能被调用一次,第二次调用不能保证返回,且调用 join()函数的线程必须不能是当前线程。Join()函数结束时唤醒在等待队列中的所有线程,因此需要实现 join()方法和修改finish()方法。方案:(1)Kthread 的 join()中的 Lib.assertTrue(this!=currentThread)已经实现线程
6、只能调用一次 join()方法,根据要求,在调用 join()方法时,让当前运行线程休眠,并将当前运行的线程加入到一个阻塞队列中。(2)在线程结束时,finish()函数循环唤醒所有被阻塞的线程。Finish()函数在 run()函数返回时自动调用,同样可以被直接调用。但当前唯一运行的线程不能被 finish()函数立即结束,只有当其他线程运行时才可结束。2.1.3 关键点与难点由于 java 派生于抽象类的对象无法实例化,在运行时很可能出现空指针异常。只能直接利用抽象类的对象调用相关方法。2.1.4 实现代码public void join()Lib.debug(dbgThread,“Joi
7、ning to thread:“+toString();/判断要调用的进程是否为当前进程(线程只能调用一次 join()方法)Lib.assertTrue(this!=currentThread);/系统关中断,当前线程休眠oolean intStatus=Machine.interrupt().disable();if(status!=statusFinished)/调用另一个要调用的进程,将当前运行的线程加入到一个阻塞队列中。waitForJoin.waitForAccess(currentThread);/当前进程睡眠等待被调用进程结束sleep();Machine.interrupt(
8、).restore(intStatus);public static void finish()Lib.debug(dbgThread,“Finishing thread:“+currentThread.toString();/系统关中断Machine.interrupt().disable();/当前进程运行结束的标志Machine.autoGrader().finishingCurrentThread();Lib.assertTrue(toBeDestroyed=null);/表示当前进程要结束了toBeDestroyed=currentThread;/当前进程的状态被修改为运行结束cur
9、rentThread.status=statusFinished;/调用等待队列上的第一个进程Kthread waitThread;while(waitThread=currentThread.waitForJoin.nextThread()!=null)/唤醒等待队列上所有被阻塞的进程waitThread.ready();sleep();2.2.2 2 TaskTask 1.21.2 实现条件变量实现条件变量2.2.1 题目要求利用中断有效和无效所提供的原子性直接实现条件变量。我们已经提供类似的例子实例实现信号量。你要按此提供类似的条件变量的实现,不能直接利用信号量来实现(你可以使用 loc
10、k,虽然它间接地调用了信号量)。在你完成时要提供条件变量的两种实现方法。你的第二种条件变量实现要放在 nachos.threads.Condition2 中。2.2.2 题目分析与实现方案分析:条件变量使我们可以睡眠等待某种条件出现,是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使”条件成立”(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。方案:threads.Lock 类提供了锁以保证互斥。在临界代码区的两端执行Lock.acquire()和Lock.release()即可保证同时只有一个线程
11、访问临界代码区。条件变量建立在锁之上,由 threads.Condition 实现,用来保证同步。每一个条件变量拥有一个锁变量。(1)sleep()在条件变量的控制下 sleep()函数自动释放相关锁并进入睡眠状态,直到令一个线程用 wake()唤醒它,需要在函数的开始和结尾处关或允许中断保证原子性。当前线程必须拥有相关锁,阻塞进程在 sleep()函数返回之前线程将会自动再次拥有锁。即调用这个方法的线程将自己挂起到等待队列,阻塞自己的同时将自己拥有的锁交出去,之后等待锁的分配。拿到锁的线程再次拥有权限接受检验。(2)wake()唤醒条件变量队列中第一个线程,在试验中利用从线程队列中取出线程用
12、 Kthread.ready()实现唤醒,加入就绪队列。(同样要在wake 函数利用中断保证原子性)(3)wakeall()函数的实现依赖于 wake()。只需不断地 wake 挂在条件变量上的线程直到队列为空为止。2.2.3 关键点与难点题目要求直接实现条件变量,不能直接利用信号量。所以互斥锁必须要有,它是线程们有秩序的接受条件变量检验的保证。等待队列必须要有,不满足条件的线程都要挂在上面。2.2.4 实现代码public static void sleep()Lib.debug(dbgThread,“Sleeping thread:“+currentThread.toString();Li
13、b.assertTrue(Machine.interrupt().disabled();if(currentThread.status!=statusFinished)/锁住当前线程currentThread.status=statusBlocked;/运行下一个线程runNextThread();public void wake()Lib.assertTrue(conditionLock.isHeldByCurrentThread();if(!waitQueue.isEmpty()(Semaphore)waitQueue.removeFirst().V();public void wakeA
14、ll()Lib.assertTrue(conditionLock.isHeldByCurrentThread();while(!waitQueue.isEmpty()wake();2.2.3 3 TaskTask 1.31.3 完成完成 AlarmAlarm 类类2.3.1 题目要求完成 Alarm 类,通过 waitUntil(long x)方法实现。一个线程通过调用 waitUntil(long x)方法将自己挂起,一直到经过 x 时间再被唤醒。这对现实操作很有用,例如,光标的周期闪烁。线程经过 x 时间后唤醒,但不需要立刻运行,而是加入 readyqueue 中。不建立任何多余的线程实现
15、 waitUntil(),只需要修改 waitUntil()中断处理程序和计时器。waitUntil()不受限于任何一个线程,任何线程可以调用它实现被挂起。2.3.2 题目分析与实现方案分析:Alarm 类使用硬件定时器提供抢占,并允许线程挂起到某个时间。分配的新闹钟设置机器的定时器中断处理程序实现本闹钟的回调,同时 Nachos 只在有一个计时器的情况下正常运行。定时器中断处理程序被称为机器计时器定期(大约每 500 时钟周期)。当前线程产生后,如果有另一个必须运行的线程,则强制上下文切换。当前线程睡眠至少 x 时间周期,在定时器中断处理程序中将其唤醒。当现在时间(current time)
16、=(WaitUntil called time)+(x)时,线程必须被唤醒(在调度准备集)在第一个定时器中断的产生时。方案:(1)与 Alarm 类有关的是 machine.Timer 类,它在大约每 500 个时钟滴答使调用回调函数(由 Timer.setInterruptHandler 函数设置)。因此,Alarm 类的构造函数中首先要设置该回调函数Alarm.timerInterrupt()。timerInterrupt()方法在每一次 timer 产生时间中断时遍历队列,检查队列中的时间状态,当线程到了等待的时间就把线程从队列中取出放入就绪队列。(2)waitUntil()方法使用了一
17、个队列可以存放线程以及唤醒时间,这个队列以时间为序的有序队列。每次调用时,把当前线程和唤醒时间加入队列,等待唤醒。在调用 waitUntil(x)函数时,首先得到关于该线程的信息(线程:当前线程,唤醒时间:当前时间+x),该线程设定唤醒时间并阻塞,并调用 sleep 操作使当前线程挂起,放入队列中。在时钟回调函数中(大约每 500 个时钟间隔调用一次)有一次中断,中断时则依次检查队列中的每个对象,将队列中此时应当唤醒的进程加入就绪队列。如果唤醒时间大于当前时间,则将该对象移出队列并执行 wake 操作将相应线程唤醒。(3)Waiter()是一个用来管理和存储多个 Kthread 及其唤醒时间的
18、内部类,属性分别为该 Kthread 与其唤醒时刻 waketime。2.3.3 关键点与难点线程调用 waitUntil 方法之后会终止,该线程设定唤醒时间并阻塞,直到传入的时间之后才可以执行。线程只是放入就绪队列,等待分配。可以使用一个线程队列,但是不能产生额外的线程。Timer 每 过 500 个 clock ticks 会 产 生 一 个 timeInterrupt。timeInterupt 时,会运行 handle()线程,将 handler 线程功能设置为将队列中此时应当唤醒的进程加入就绪队列。2.3.4 实现代码class Waiter Waiter(long wakeTime,
19、Kthread thread)this.wakeTime=wakeTime;this.thread=thread;private long wakeTime;/唤醒时间private Kthread thread;/等待的线程private LinkedList waitlist;/存放线程以及唤醒时间public void waitUntil(long x)/系统关中断oolean intStatus=Machine.interrupt().disable();/for now,cheat just to get something working(busy waiting isbad)/确
20、定唤醒的时间long wakeTime=Machine.timer().getTime()+x;Waiter waiter=new Waiter(wakeTime,Kthread.currentThread();/将线程加入到等待队列上waitlist.add(waiter);System.out.println(“线程:”+Kthread.currentThread().getName()+“t 休眠时间:”+Machine.timer().getTime()+“t 下次唤醒时间:”+wakeTime);/当前线程设定唤醒时间并阻塞,挂起Kthread.sleep();/开中断Machine
21、.interrupt().restore(intStatus);2.2.4 4 TaskTask 1.41.4 条件变量实现同步消息条件变量实现同步消息2.4.1 题目要求使用条件变量来实现一个字长信息的发送和接收同步。使用 voidspeak(int word)和 int listen()函数来实现通讯(Communicator)类的通讯操作。Speak 函数具有原子性,在相同地 Communicator 类中等待 listen 函数被调用,然后将此字发生给 listen 函数。一旦传送完毕,两个函数都返回(listen 函数返回此字)。2.4.2 题目分析与实现方案解决方案要满足使用同一个
22、通讯对象实例中多个 speaker 和listener 能够相互通讯。(注意:这种情况等于 0 字长的缓冲区;既然缓冲区没用空间,那么需要生产者和消费者直接进行交互,要求他们相互等待)。每一个通讯实例只能使用一个 lock 类,如果使用多于一个 lock 类,会将事情复杂化。每个 Communicator 拥有的锁(保证操作的原子性)和与该锁联系的两个条件变量用于保证 speaker 和 listener 间的同步。在 speak 函数中,首先检查是否已经有 speaker 在等待(speaknum0)或无 listener等待,满足这两种情况就挂起。若不满足,则设置变量,准备数据并唤醒一个
23、listener。在 listen 函数中,增加一个 listener 后,首先,然后这个问题其实是一个缓冲区长度为 0 的生产者/消费者问题。Speak():先获得锁,然后进行判断,如果没有听者等待,就要把说者放入队列然后睡眠。如果有听者等待,就要唤醒一个听者,然后传递消息,最后释放锁。Listen():先获得锁,然后进行判断尝试唤醒 speaker,如果没有说者等待,就要把听者放入队列然后睡眠。如果有说者等待,就要唤醒一个说者,将自己挂起以等待 speaker 准备好数据再将自己唤醒,然后传递消息,最后释放锁。2.4.3 关键点与难点当有多个 speaker 和 listener 时,它们
24、也只能是一对一的,即一个speaker只能将数据发送到一个listener,一个listener也只能接收来自一个 speaker 的数据,其余的 speakers 和 listeners 都需要等待。多个speaker 阻塞时需要保存每一个 speaker 的 word,阻塞的 speaker 挂在Condition 对象的 Queue 队列上。因为无缓冲区,listener 唤醒说者后要先挂起,消息在 speaker 准备好后才传递。2.4.4 实现代码public class Communicator public Communicator()lock=new Lock();speake
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计 实验 报告 proj1

限制150内