一 题目
project1:实现nachos操作系统的project1中的join()方法,condition2类,Alarm类,Communicator类,PriorityScheduler类和Boat类
project2:实现nachos操作系统的project2中的creat open read write close unlink 文件系统调用,修改UserProcess.readVirtualMemory 和UserProcess.writeVirtualMemory使操作系统能够运行多用户程序,实现exec join exit系统调用,实现LotteryScheduler类
二 实验目的
熟悉nachos操作系统,深入理解操作系统内核
了解用户程序的加载过程以及多用户进程的内存分配机制
三 实验要求
完成nachos,提交设计文档和你的代码
四 实验说明,程序代码及测试结果
Project1:
1 join()
要求实现join()方法,注意,其他线程没必要调用join函数,但是如果它被调用的话,也只能被调用一次。join()方法第二次调用的结果是不被定义的,即使第二次调用的线程和第一次调用的线程是不同的。无论有没有被join,一个进程都能够正常结束 (a) 设计思想
当线程B执行A.join()时,将B放入A的等待队列,直到A完成时,唤醒在等待队列中的所有线程,因此需要实现join()方法和修改finish方法 (b) 源代码
public void join() {
Lib.debug(dbgThread, \ + toString()); Lib.assertTrue(this != currentThread); Lib.assertTrue(join_counter == 0); join_counter++;
boolean status = Machine.interrupt().disable(); if (this.status != statusFinished) {
waitQueue.waitForAccess(KThread.currentThread()); currentThread.sleep();
}
Machine.interrupt().restore(status); }
public static void finish() {
Lib.debug(dbgThread, \ + currentThread.toString());
Machine.interrupt().disable();
Machine.autoGrader().finishingCurrentThread(); Lib.assertTrue(toBeDestroyed == null); toBeDestroyed = currentThread;
currentThread.status = statusFinished;
KThread thread = currentThread().waitQueue.nextThread(); if (thread != null) {
thread.ready(); } sleep(); }
(c) 程序截图
线程1每次执行打出执行的次数,每次执行过后放弃cpu,线程2打出successful,线程2执行thread1.join().通过截图可以看出代码正确
2 Condition2
通过使用开关中断提供原子性来直接实现条件变量,我们利用信号量提供了一个简单的实现方式,你的工作就是不直接使用信号量提供相同的实现(你或许使用锁,即使它们也间接的使用了信号量)。一旦你实现了 ,你将会有两种可选
择的实现方式来提供相同的功能。你的第二种条件变量的实现必须放在Condition2中 (a)设计思想
Condition2是对使用该条件变量的线程进行管理,所以要把在这个条件变量上等待的进程储存起来,因此可以使用一个队列。
sleep()方法是把等待该条件变量的线程阻塞,放入等待队列,直到执行了wake()并且获得cpu才能继续执行,执行步骤:关中断,释放锁,把线程放入等待队列,获得锁,开中断 。
wake()方法是把条件变量中的线程移出,放入就绪队列。执行步骤:关中断,线程移出等待队列移入就绪队列,开中断
wakeAll()方法是将条件变量中的所有线程移出,移入就绪队列 (b)源代码
public void sleep() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread()); boolean status=Machine.interrupt().disable(); conditionLock.release();
waitqueue.waitForAccess(KThread.currentThread()); KThread.currentThread().sleep(); conditionLock.acquire();
Machine.interrupt().restore(status);
}
public void wake() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread()); boolean status=Machine.interrupt().disable(); KThread thread=waitqueue.nextThread(); if (!(thread==null)) thread.ready();
Machine.interrupt().restore(status);
}
public void wakeAll() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread()); boolean status=Machine.interrupt().disable(); KThread thread=waitqueue.nextThread(); while(!(thread==null)) { thread.ready();
thread=waitqueue.nextThread(); }
Machine.interrupt().restore(status);
} (c)程序截图
线程1线程 2分别请求锁和条件变量,然后释放锁和条件变量,图中可以看出代码正确
3 Alarm类
实现Alarm类,线程调用waitUntil方法之后会终止,直到传入的时间之后才可以执行。线程没必要在等待的时间之后立刻执行,只是把它放入ready队列,等待分配cpu。可以使用一个线程队列,但是不能产生额外的线程。 (a) 设计思想
waitUntil()方法使用了一个队列可以存放线程以及唤醒时间,这个队列以时间为序的有序队列。每次调用时,把当前线程和唤醒时间加入队列,等待唤醒。
timerInterrupt()方法在每一次timer产生时间中断时遍历队列,检查队列中的时间状态,当线程到了等待的时间就把线程从队列中取出放入就绪队列。
KThreadWakeTime类是一个内部类用于联系线程和唤醒时间 (b) 源代码
public void waitUntil(long x) {
boolean status = Machine.interrupt().disable(); long waketime = Machine.timer().getTime() + x;
KThreadWakeTime kthreadwaketime = new KThreadWakeTime( KThread.currentThread(), waketime); int size = linkedlist.size(); if (size == 0)
linkedlist.add(kthreadwaketime); else
for (int i = 0; i < size; i++) {
if (waketime < linkedlist.get(i).getWakeTime()) { linkedlist.add(i, kthreadwaketime); break; }
if (i == size - 1
&& waketime >= linkedlist.get(i).getWakeTime()) linkedlist.add(i + 1, kthreadwaketime); }
KThread.currentThread().sleep(); Machine.interrupt().restore(status); }
public void timerInterrupt() {
boolean status = Machine.interrupt().disable(); long currenttime = Machine.timer().getTime(); int size = linkedlist.size();
if (size == 0)
; else
for (int i = 0; i < size; i++) {
if (currenttime < linkedlist.get(i).getWakeTime()); else {
KThread thread = linkedlist.get(i).getThread(); thread.ready();
linkedlist.remove(i);
size--; i = 0;
currenttime = Machine.timer().getTime(); } }
KThread.currentThread().yield(); Machine.interrupt().restore(status);
}
public class KThreadWakeTime {
private KThread thread = null; private long waketime = 0;
public KThreadWakeTime(KThread thread, long waketime) {
this.thread = thread;
this.waketime = waketime; }
public KThread getThread() { return thread;
}
public long getWakeTime() {
return waketime; }
}