




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、课 程 设 计 报 告基于nachos的线程工作机制设计与实现1. 准备工作31.1 阅读英文版向导31.1.1 Nachos 和 Java端口31.1.2 Nachos 虚拟机41.2 jdb的使用41.3 代码分析过程51.3.1编译51.3.2 分析执行流程51.3.3 解读代码52. Project0:阅读代码和说明,理解Nachos的工作方式62.1 Nachos模拟的物理机的运行机制62.1.1 模拟物理机的boot过程72.1.2 模拟的硬件设备的工作原理82.2 Nachos中线程运行机制82.2.1 线程包与machine包中的TCB的关系82.2.2 线程调度92.2.3
2、创建线程的过程,创建多个线程的过程92.3 Nachos中支持用户进程的机制103. Project1: 线程工作机制113.1 需求分析113.1.1 开发背景113.1.2 系统开发环境需求113.1.3 系统目标113.2 系统总体设计113.3 系统详细设计123.3.1 A部分123.3.2 B部分133.3.3 C部分133.3.4 D部分143.4 系统实现(主要代码)143.4.1 条件变量的实现143.4.2 时钟定时功能153.4.3 进程同步收发字的实现163.5 系统测试163.5.1 同步链表及Alarm的测试163.5.2 Communicator测试194. 实现
3、项目的过程与步骤205. 遇到的困难与获得的主要成果221. 准备工作1.1 阅读英文版向导首先,我阅读了University of California Berkeley Computer Science 162 Operating Systems and Systems Programming Course Reader for Spring 2008 并做了翻译,部分翻译如下,在做了这些大致了解之后,我才开始解读代码工作。Nachos-5.0j向导:1. Nachos and the Java PortNachos和Java端口2. Nachos MachineNachos 虚拟机3.
4、Threads and Scheduling线程和调度4. The Nachos Simulated MIPS MachineNachos 模拟 MIPS 虚拟机5. User-Level Processes用户级的程序1.1.1 Nachos 和 Java端口1) 为什么实用Java语言?先不管Nachos的成功,有好多原因让我们相信Java更加有用:Java比C+更加简单。没有必要把Nachos限制在一部分语言上,学生不用理解所有的语言Java是一种安全类型,C+不是。C+程序编写者可以写溢出数组,但是这其实是一个很大的问题,导致一些项目组无法在限定的时间内找出工程中的错误,主要是因为这些
5、错误与操作系统本身无关。 用Java做一个虚拟机层次的工程比C+工程更加合理。现在很多本科数据结构课,包括伯克利大学,现在都是用Java,而不是C+,学生们了解Java更多。Java是相对便携的。Nachos4.0用不便携的集合来支持多线程。在Nachos4.0中添加一个新的目标需要为端口编写更多的代码。2) Java好用吗?大家最关心的问题就是Java的速度问题了。这是一个无可争议的事实就是Java程序的运行速度比C+设备慢。这个结论令人迷惑,虽然:在Nachos4.0的调试周期中编译时最重要的部分。因为Javac每次调用时都尽可能多的编译,Nachos5.0j实际上编译的比Nachos4.
6、0快的多。在网络上产生大文件更加减缓编译的周期。Nachos5.0j 的.class文件比Nachos4.0的.o文件小的多,甚至是用-O编译时也是。这是因为C+的模板,模板是一种没有精巧的编译器或者管理器就是变得非常大。安全类型的语言是广为人知的让调试周期更加高效的语言。另一个普遍的担忧是用安全类型的语言写一个操作系统是不现实的。这里所说的不现实的并不是你想象中的那样。真正的错做系统的两方面已经不使用Java了,但是没有一个是严格的:自从JVM为Nachos5.0j提供了线程机制,上下文转换的代码就隐藏起来了。在Nachos4.0中,学生可以读分块的用来在线程之间转换的代码。但是,就像前面提
7、到的,这会产生一个适用性的问题。内核可以指定内核空间而不释放它们,垃圾回收装置会自动释放它们。子啊Linux中,这与把所用调用移到kfree中类似。但是,这是一种在概念上最简单的内核资源分配方式,Nachos的内核一定要直接管理进程之间物理页的分配,例如,当进程结束时必须关闭文件。1.1.2 Nachos 虚拟机Nachos模拟一个真实的CPU和硬件设备,包括中断和内存管理。Java中的包nachos.machine提供了这个模拟器。1)安装NachosNachos模拟器用nachos.conf文件安装在不同的工程上。它详细描述了模拟器中包含哪些硬件设备和Nachos内核如何使用硬件。工程的说
8、明书包括适当的配置文件,如果必要的话,可以改动工程的宣传册文件需要完成这个工程。2) 启动进程Nachos的启动进程类似于真实的虚拟机。nachos.machine.Machine.class的一个实例用来启动Nachos。计算机硬件(虚拟机类)首先初始化设备包括中断控制器,定时器,电梯控制器,MIPS进程,和文件系统。虚拟机类对象把控制权交给特定的自动分级AutoGrader装置,相当于从硬盘上载入启动引导程序的代码。是AutoGrader产生了Nachos内核,并开始运行系统。学生们不必关心这一步启动工作,真正有趣的部分从内核开始。Nachos的内核仅仅是nachos.machine.Ke
9、rnal的一个子类。比如说,线程项目用的是nachos.threads.ThreadedKernel。3)Nachos的硬件配置Nachos虚拟机包括很多硬件设备。有一些在现代计算机中普遍存在(如:网络接口),但有些(比如说电梯控制)是Nachos特有的。Machine文件中的大多数类是硬件模拟的一部分,而在machine文件之外的类是Nachos操作系统的。4)中断管理nachos.machine.Interrupt 类通过维持一个事件队列来模拟1.2 jdb的使用在跟踪程序分析执行流程时仅仅使用System.out输出信息只能进行一些简单的验证,很难完成庞大工程的调试分析,而这时候jdb就
10、显得很威武了。jdb提供了强大的调试功能,这里我只使用了一些常用命令。run - 开始运行程序stop in 包.类.函数名 - 设置在对应函数进入时触发的断点stop at 包.类:行号 - 设置在指定文件特定行的断点print 变量名或者表达式 - 输出变量或者经过运算的值cont - 在断点处理后继续执行threads - 显示正在运行的线程suspend/resume id - 挂起/恢复一个线程thread tid - 切换到特定线程在我的分析过程中最复杂的就是对于多个线程同时执行时的分析,为了跟踪一个线程如何等待另一个线程的唤醒信号,不得不不断地在线程间切换,切换前又要挂起当前的线
11、程,这时一个很复杂的过程。1.3 代码分析过程1.3.1编译从README开始加入环境变量:nachos/bin export PATH=/home/minda/Desktop/课件OS-2011/nachos/bin:$PATHmakenachos 运行1.3.2 分析执行流程 分析nachos脚本,发现脚本中有 java nachos.machine.Machine找到machine.java开始从main函数分析源代码进入autoGrader.java分析出selfTest进行演示,进程创建进入Kernel.java因为Kernel是一个抽象类,所以肯定有实现Kernel的实例nacho
12、s.conf配置文件中包含Kernel.kernel = nachos.threads.ThreadedKernel在threadedKernel.java中,找到selfTest()进入Kthread.java通过selfTest()找到PingTest在PingTest里就包含了完整的运行proj1的信息PingTest是继承runnable接口的类,runnable是一个Java中的接口1.3.3 解读代码解读KThread.java代码:解析KThread中的方法:KThread():创建线程时如果是第一个线程,即当前线程未空,就调用ThreadedKernel.scheduler 也
13、就是nachos.threads.RoundRobinScheduler的newThreadQueue方法,并创建一个先进先出队列,并创建一个空闲线程,名为idle如果当前线程非空,就创建线程控制块tcb();setName();设置名字getName();取得名字toStirng();重写toString方法compareTo(Object o);线程之间通过线程id进行比较fork()导致线程开始执行,结果就是两个线程正在执行,一个是当前线程,一个是被执行的线程。Finish()结束当前线程并加入调度销毁线程,当一个线程的方法返回时自动执行该方法。如果当前的线程因为栈或者另一个之星状态一直
14、在被使用不能被立即销毁,那么这个线程就会在其他线程运行时自动销毁。Sleep()由于当前线程结束或者阻塞,而放弃CPU;如果当前的线程被阻塞,一些线程会把它唤醒,然后将它加入就绪等待队列,这样它可以被重新调度了。或者是该线程结束,那么就调度此线程在下一个线程运行时销毁该线程。调用sleep就可以让CPU切换给其他线程执行ready()将当前线程加入就绪队列,并将该线程的状态改为ready状态run()将这个线程放在CPU上执行,保存进程的当前状态并调用新线程,载入新线程的状态。新线程就成了当前线程,如果新线程与旧线程是相同的,这个方法必须被调用,之前运行的线程必须从运行状态转到阻塞或者就绪等待
15、状态(取决语之前运行的线程在sleep状态还是yield状态)2. Project0:阅读代码和说明,理解Nachos的工作方式2.1 Nachos模拟的物理机的运行机制Nachos的线程调度是属于内核的一部分,线程调度与Nachos的其他部分的关联可以从下图看出:下面将分别对模拟物理机的boot过程、模拟的硬件设备的工作原理进行详细分析,其中重点是线程调度的原理及实现过程。2.1.1 模拟物理机的boot过程1)读配置文件Config.load(configFileName);configFileName = nachos.conf在nachos.conf中,主要有两个比较关键Threade
16、dKernel.scheduler = nachos.threads.RoundRobinScheduler #nachos.threads.PriorityScheduler表示Kernel中运行RoundRobinSchedule,PriorityScheduler,LotteryScheduler中的哪一个调度器。选定Kernel的类型,这里表示可实现多种Kernel进行选择测试。Kernel.kernel = nachos.threads.ThreadedKernel2)初始化安全管理器,权限管理器3)创建硬件设备createDevices();每一个硬件初始化它的权限和中断4)检查组
17、件完整性checkUserClasses();即检查Nachos的各个类是否都完整以及部分关键函数是否被实现。检查的类包括:java.lang.Object,java.lang.Runnable,java.lang.String,nachos.machine.Kernel,nachos.machine.FileSystem,nachos.machine.RiderControls,nachos.machine.ElevatorControls,nachos.machine.RiderInterface,nachos.machine.ElevatorControllerInterface,nac
18、hos.threads.Alarm,nachos.threads.ThreadedKernel,nachos.threads.KThread,nachos.threads.Communicator,nachos.threads.Semaphore,nachos.threads.Lock,nachos.threads.Condition,nachos.threads.Condition2,nachos.threads.Rider,nachos.threads.ElevatorController5)引导内核启动autoGrader构建内核并初始化,把操作权转给内核完成引导过程2.1.2 模拟的硬
19、件设备的工作原理1)中断机制中断机制模拟了底层的硬件中断,监视所有可能引发中断的硬件,也监视模拟出来的时钟Timer,这里只模拟单核cpu ,不考虑cpu之间的同步问题。对硬件提供开启enable()和关闭中断disable()的方法对软件提供开启enable()、关闭disable()、保存、恢复restore()schedule() 由中断权限管理InterruptPrivilege()根据中断类型type安排中断的处理顺序用一个集合TreeSet存储等待处理的中断,在时钟的tick过程中,通过checkIfDue()方法依次处理pending中等待处理的中断。2)定时器定时器上层向cpu
20、发送定时器中断,下层向程序提供设置定时器的接口,可以按一定的时间间隔执行特定的代码。在每一次被触发中断时在callBack的回调函数handler中安排下一次中断。3)可能的其他设备比如磁盘、网络、键盘,这些设备为后面的工程测试提供了支持。2.2 Nachos中线程运行机制2.2.1 线程包与machine包中的TCB的关系1)KThread构造函数创建线程时创建TCB,若当前无线程时,创建第一个线程直接使用main线程执行并将tcb指向currentTCB。2)当线程调用fork()方法,即在增加一个线程时调用tcb.start()3)当线程调用run()方法,使CPU运行当前线程发生上下文
21、切换时,调用tcb.contextSwitch切换到新的线程4)恢复运行环境时调用销毁被标记删除状态的tcb2.2.2 线程调度线程调度是通过队列控制的,队列决定线程切换顺序。线程调度主要在文件KThread.java中1)在系统创建第一个线程时创建线程队列readyQueue2)每次创建线程时将线程加入队列3)当线程状态为就绪时,在线程队列中标记为可以进入,加入等待队列waitQueue并等待调度4)发生线程切换时,即调用yield()方法或sleep()方法时,将从线程队列中取下一个线程执行5)每一个线程都有一个优先级,由调度器对线程的优先级进行增减,决定线程队列中线程的出队顺序。不同的调
22、度器对于优先级控制的实现不同。Schedule 分为RoundRobinSchedule,PriorityScheduler,LotteryScheduler。RoundRobinSchedule为轮换调度调度器,使用FiFo队列PriorityScheduler为带权优先调度器,根据线程执行时间、启动顺序等计算优先级LotteryScheduler为随机调度器,随机决定出队顺序2.2.3 创建线程的过程,创建多个线程的过程创建一个线程时先创建线程TCB,指定线程名setName(),绑定Runnable对象即使用调用tcb.start(new Runnable() public void r
23、un() runThread(); ); 内核创建第一个空闲线程时直接命名 main并设为当前线程。tcb = TCB.currentTCB(); name = main;fork()方法启动新线程,具体过程是,保存cpu状态intStatus = Merrupt().disable(),调用TCB的start方法创建java线程执行到线程切换tcb.start();再恢复 cpu状态,同时引发新线程执行,若有多个线程则唤醒下一个线程。 对于创建的第一个线程直接使用main线程执行。2.3 Nachos中支持用户进程的机制因此模块与Project1关联并不密切,此处仅作粗略
24、阅读,了解其工作原理即可。3. Project1: 线程工作机制3.1 需求分析3.1.1 开发背景Nachos 是一个教学操作系统,首先肯定它是一个真正的操作系统。它有两个CPU,一个宿主机 CPU,一个模拟 MIPS 的 CPU,Nachos 运行在模拟 CPU 上。很难从某一方面去讲解 Nachos 的运行机制,因为 Nachos 是一个整体,用到很多全局变量,各函数之间关系紧密,看代码的时候随时候不仅要关注局部,还要留意整体变化,这一点在学习 Nachos 时很重要。Nachos 最重要的部分是进程管理,理解了这部分,内存、IO、磁盘和文件管理就容易学了(其实在学习进程管理这部分时,其
25、它功能也就顺便了解了),因此我重点介绍 Nachos 的进程管理部分,其它不做特别说明。刚接触 Nachos 时不要急于看代码,先看帮助文档,了解整体架构,然后有的放矢的阅读代码,直接从代码入手是很难找到头绪的。3.1.2 系统开发环境需求 Windows+Cygwin或linux,考虑到cygwin本身是模拟linux环境,为了更高兼容和稳定性,我选择使用linux环境 ubuntu 12.04; jdk 1.5/1.6 我使用ubuntu自带的openjdk 系统目标建立一个完整的线程工作系统。第一步是阅读和理解当前Nachos系统中的部分线程系统的代码。 当前代码中已经
26、实现了线程的生成(fork操作),线程的终结和用于同步的信号量机制。该部分代码还包括在信号量上建立的锁(locks)和条件变量等。3.2 系统总体设计1)实现条件变量,通过中断使能和不使能两种操作提供条件变量上的原子操作。按照nachos.threads.Condition,其中已经实现了一个使用信号量机制的例子。 在不使用信号量的情况下提供一种等同的实现方法(使用锁)。 实现放在nachos.threads.Condition2类中.SynchList.java文件对其进行测试。2)实现KThread.join()方法。 该方法只被调用一次。3)完成Alarm类,实现waitUntil(lo
27、ng x)方法。 一个线程调用waitUntil将挂起自己的执行,直到时间变为nowx。 线程在唤醒后将它们放入到等待队列中。不生成其他的线程实现waitUntil方法,修改waitUntil方法和定时器中断处理程序。waitUntil不限于一个线程,任何数目的线程均可调用它,每次一个线程挂起。现在的代码只是让程序能运行,并没有真正实现该功能。挂起该进程,就必须挂起到一个地方,能够根据时间再次唤醒该进程4)实现同步发送和接收一个字消息的方法,使用条件变量,不使用信号量。 实现Communicator类中的speak和listen方法。 speak是原子操作,等待直至该Communicator类
28、中的listen方法被调用然后传递该字给listen方法。 一旦传递完成两个方法均可返回。同样的,listen方法等待直到speak方法被调用,一旦传递完成两个方法均可返回。实现方法必须能够在以下情况中工作:即使同一个Communicator有多个speaker或者listener在使用。 每一个cmmunicator只能使用一个锁。如果使用超过一个锁,那么情况就复杂了。实现同步机制, 并使用类Communicator。5)完成基于优先级的线程调度,PriorityScheduler类。基于优先级的调度是实时操作系统中的关键模块。要使用基于优先级的调用,需要修改nachos.conf中的一行,
29、以便指定调度类。注意所有的调度类均扩展自nachos.threads.Scheduler抽象类,并实现getPriority(), getEffectivePriority(), and setPriority(),increasePriority() and decreasePriority()方法。在选择哪一个线程出队列时,调度程序总是选择具有最高优先级的线程。当有多个线程具有相同的优先级时,调度程序总是选择在队列中等待时间最长的线程。3.3 系统详细设计3.3.1 A部分要求实现条件变量,通过中断使能和不使能两种操作提供条件变量上的原子操作。按照nachos.threads.Condit
30、ion,其中已经实现了一个使用信号量机制的例子。 在不使用信号量的情况下提供一种等同的实现方法(使用锁)。实现放在nachos.threads.Condition2类中。通过Condition与Condition2的对比发现,Condition2中构造方法中不含waitQueue = new LinkedList();sleep()方法中不含Semaphore waiter = new Semaphore(0);waitQueue.add(waiter);waiter.P();wake()方法中不含if (!waitQueue.isEmpty()(Semaphore) waitQueue.re
31、moveFirst().V();wakeall()方法中不含while (!waitQueue.isEmpty()wake();需要在不使用semaphore的前提下完成Condition2,并实现相同的功能。以下将对Condition2的构造方法,sleep(),wake(),wakeAll()这4个方法的设计进行详细说明:构造方法:创建一个ThreadQueue waitQueue初始化为空,计数器 value,初始值为0。waitQueue用来存放正在在条件变量上等待的线程,value存放不需等待的线程个数,value的存在是防止线程加入等待队列之前已经有一个线程将其唤醒,这样可能导致线
32、程永不再被唤醒,一个互斥锁mutex用于同步对队列和计数器的访问。sleep():判断value,如果大于0,此时表明在sleep之前已经有wake被调用过,所以将其减1直接返回;若等于0,将该线程加入线程队列waitQueue并调用KThread.sleep()将其挂起。整个过程是一个原子操作,使用mutex加以保护。wake():队列若非空,表明此时有正在该条件变量上等待的线程,将队列的第一个线程取出并调用KTerrupt()唤醒;若队列为空,将value加1并返回。整个过程是一个原子操作,使用mutex加以保护。wakeAll():直接将线程队列中所有的线程取出并唤醒。
33、整个过程是一个原子操作,使用mutex加以保护。3.3.2 B部分要求是完成Alarm类,实现waitUntil(long x)方法。 一个线程调用waitUntil将挂起自己的执行,直到时间变为nowx。 线程在唤醒后将它们放入到等待队列中。不生成其他的线程实现waitUntil方法,修改waitUntil方法和定时器中断处理程序。waitUntil不限于一个线程,任何数目的线程均可调用它,每次一个线程挂起。现在的代码只是让程序能运行,并没有真正实现该功能。挂起该进程,就必须挂起到一个地方,能够根据时间再次唤醒该进程。Alarm构造函数调用setInterruptHandler(Runnab
34、le handler)把timerInterrupt()方法注册为时钟回调方法,即时钟每次tick时调用。初始化一张线程等待表,线程等待表存放一种数据结构,该数据结构包含正在等待的线程以ID及需要被唤醒的时间。Alarm要求实现waitUntil(long x)方法,该方法用于等待一定的时间将线程唤醒,等待时间长度为x,Nachos的时间采用模拟的tick计数,所以实现时应使用Machine.timer().getTime()方法获取当前时间加上等待的时间长度表示线程被唤起的时间点,加入到线程等待表中,并调用KThread.sleep()挂起当前线程。timerInterrupt()方法检查线
35、程等待表,将其中超时的线程唤醒,这里可以用优先队列存储表,优先队列将按超时时间排序,检查时便不需要遍历整张表,提高效率。3.3.3 C部分要求是实现同步发送和接收一个字消息的方法,使用条件变量,不使用信号量。 实现Communicator类中的speak和listen方法。 speak是原子操作,等待直至该Communicator类中的listen方法被调用然后传递该字给listen方法。 一旦传递完成两个方法均可返回。同样的,listen方法等待直到speak方法被调用,一旦传递完成两个方法均可返回。实现方法必须能够在以下情况中工作:即使同一个Communicator有多个speaker或者
36、listener在使用。 每一个cmmunicator只能使用一个锁。实现同步机制, 并使用类Communicator。使用类似同步链表SynchList中selftest方法的方式,同步链表SynchList已经实现了原子操作,所以此时可保证speak和listen方法均为原子操作。speak方法调用SynchList.add将数据加入链表中,listen方法调用SynchList.removeFirst方法从链表中取出数据,SynchList本身已经通过条件变量实现了当链表空时调用removeFirst会等待直到链表非空才返回的功能。while (list.isEmpty()listEmp
37、ty.sleep();3.3.4 D部分要求是完成基于优先级的线程调度,PriorityScheduler类。基于优先级的调度是实时操作系统中的关键模块。要使用基于优先级的调用,需要修改nachos.conf中的一行,以便指定调度类。注意所有的调度类均扩展自nachos.threads.Scheduler抽象类,并实现getPriority(), getEffectivePriority(), and setPriority(),increasePriority() and decreasePriority()方法。在选择哪一个线程出队列时,调度程序总是选择具有最高优先级的线程。当有多个线程具
38、有相同的优先级时,调度程序总是选择在队列中等待时间最长的线程。PriorityScheduler类中需要完善的方法主要是setPriority,getEffectivePriority和waitForAccess。构造方法中创建一个优先队列,优先队列中元素的关键字就是其对应线程getEffectivePriority的值。setPriority方法改变一个线程的优先级,并且具有触发功能,即如果在等待的队列中存在比此线程优先级高的线程时立即执行线程切换。getEffectivePriority是为解决高优先级线程等待低优先级线程时,若存在另外的高优先级线程而导致低优先级线程永远不能被执行的情况,
39、这时线程将返回其持有的锁上等待的所有线程中优先级中最高的一个给该低优先级线程,以确保它被执行。waitForAccess与getEffectivePriority配合使用,在线程需要等待sleep时调用,需要做的处理是在其所等待的线程中EffectivePriority比当前线程优先级低时将其用getEffectivePriority方法更新。3.4 系统实现(主要代码)3.4.1 条件变量的实现主要是等待与唤醒函数 public void sleep() Lib.assertTrue(conditionLock.isHeldByCurrentThread();conditionLock.re
40、lease();boolean intStatus = Merrupt().disable(); waiting +; waitQueue.waitForAccess(KThread.currentThread(); KThread.sleep();Merrupt().restore(intStatus);conditionLock.acquire(); public void wake() Lib.assertTrue(conditionLock.isHeldByCurrentThread();if (waiting 0) boolean intSta
41、tus = Merrupt().disable();KThread thread = waitQueue.nextThread();if (thread != null) thread.ready(); waiting -;Merrupt().restore(intStatus); 3.4.2 时钟定时功能 public void waitUntil(long x) long wakeTime = Machine.timer().getTime() + x;Semaphore sem = new Semaphore(0);waitTable.add(ne
42、w WaitItem(sem, wakeTime);sem.P(); public void timerInterrupt() for (Iterator x = waitTable.iterator(); x.hasNext(); ) WaitItem item = (WaitItem)x.next(); if (item.time = Machine.timer().getTime() item.sem.V(); x.remove(); 3.4.3 进程同步收发字的实现使用两个SynchList实现 public void speak(int word) wordSpeak.add(wor
43、d); wordListen.removeFirst(); public int listen() int word = (Integer)wordSpeak.removeFirst(); wordListen.add(word); return word;3.5 系统测试3.5.1 同步链表及Alarm的测试这里我把原来的ping-pong测试改为pingping-pongpong,并且ping线程在循环中使用Alarm进行延迟,更加明显的证明条件变量的稳定性,同时测试了Alarm的waitUntil方法。private static class PingTest implements Ru
44、nnable PingTest(SynchList ping, SynchList pong) this.ping = ping; this.pong = pong;public void run() for (int i=0; i10; i+) System.out.println(ping remove + i);Object o = ping.removeFirst();System.out.println(ping remove done + i);System.out.println(pong add + i);pong.add(o);System.out.println(pong
45、add done + i); private SynchList ping;private SynchList pong; public static void selfTest() SynchList ping = new SynchList();SynchList pong = new SynchList();new KThread(new PingTest(ping, pong).setName(ping).fork();for (int i=0; i5; i+) Integer o = new Integer(i);System.out.println(ping add + i); p
46、ing.add(o); ping.add(o);System.out.println(ping add done + i);/ 使用Alarm的waitUntil方法延迟 new Alarm().waitUntil();System.out.println(thread0 wake);System.out.println(pong remove + i); / Lib.assertTrue(pong.removeFirst() = o);pong.removeFirst();pong.removeFirst();System.out.println(pong remove done + i);
47、 对应输出:ping add 0ping add done 0ping remove 0ping remove done 0pong add 0pong add done 0ping remove 1ping remove done 1pong add 1pong add done 1ping remove 2thread0 wakepong remove 0pong remove done 0ping add 1ping add done 1ping remove done 2pong add 2pong add done 2ping remove 3ping remove done 3po
48、ng add 3pong add done 3ping remove 4thread0 wakepong remove 1pong remove done 1ping add 2ping add done 2ping remove done 4pong add 4pong add done 4ping remove 5ping remove done 5pong add 5pong add done 5ping remove 6thread0 wakepong remove 2pong remove done 2ping add 3ping add done 3ping remove done
49、 6pong add 6pong add done 6ping remove 7ping remove done 7pong add 7pong add done 7ping remove 8thread0 wakepong remove 3pong remove done 3ping add 4ping add done 4ping remove done 8pong add 8pong add done 8ping remove 9ping remove done 9pong add 9pong add done 9thread0 wakepong remove 4pong remove
50、done 43.5.2 Communicator测试在ThreadedKernel的selfTest中进行,两个线程一个收一个发,通过观察输出可以发现所有的发送都在对方接到后返回,所有的接收都在得到发送后返回。private class Speaker implements Runnableprivate Communicator c;Speaker(Communicator c_) c = c_;public void run() for (int i = 0; i 10; + i) System.out.println(speaker speaking + i);c.speak(i);Sy
51、stem.out.println(speaker spoken);Communicator c = new Communicator();new KThread(new Speaker(c).setName(Speaker).fork();for (int i = 0; i 10; + i) System.out.println(listener listening + i);int x = c.listen();System.out.println(listener listened, word = + x);对应输出:listener listening 0speaker speaking
52、 0listener listened, word = 0listener listening 1speaker spokenspeaker speaking 1listener listened, word = 1listener listening 2speaker spokenspeaker speaking 2listener listened, word = 2listener listening 3speaker spokenspeaker speaking 3listener listened, word = 3listener listening 4speaker spoken
53、speaker speaking 4listener listened, word = 4listener listening 5speaker spokenspeaker speaking 5listener listened, word = 5listener listening 6speaker spokenspeaker speaking 6listener listened, word = 6listener listening 7speaker spokenspeaker speaking 7listener listened, word = 7listener listening
54、 8speaker spokenspeaker speaking 8listener listened, word = 8listener listening 9speaker spokenspeaker speaking 9listener listened, word = 9speaker spoken4. 实现项目的过程与步骤项目题目确定:可以说,项目题目的确定是花费时间最长的阶段。因为需求方主要就是自己,没有组员一起讨论,我做哪个项目,其实这之间最关键的是我不仅考虑了做什么,还考虑了对我自己来说,这个项目有何意义。因为我对操作系统了解的很少,学习操作系统对我来说是第一次深入的了解操作系统,我非常想将操作系统学好,而学习操作系统最好的方法就是自己做一个操作系统。所以我选择了Nachos这个课程设计题
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 9096-2025烧结金属材料(不包括硬质合金)夏比冲击试验方法
- 宣传委员竞选课件
- 陕西省四校联考2025年物理高二下期末质量检测模拟试题含解析
- 宣传乐器课件教案
- 二零二五年度电网升级改造施工合同范本正规范本
- 二零二五年度农业保险不可撤销赔偿担保合同
- 二零二五年度财务离职员工保密协议及财务软件使用限制合同
- 二零二五年度高端商务楼日常保洁合同补充条款
- 2025版城市重要区域安全巡逻与防控服务合同
- 二零二五年度医疗器械运输与仓储设备更新改造服务合同
- 中暑防治课件图片高清版
- 脑卒中溶栓护理课件
- 2025年城建技师考试题库及答案
- 2025年中国LTCC技术行业市场现状、前景分析研究报告(智研咨询发布)
- 岭南版八年级下册美术 6色彩的表现 课件
- 湖北武汉洪山区招考聘用社区干事235人模拟检测试卷【共1000题含答案解析】
- GB/T 4854.8-2007声学校准测听设备的基准零级第8部分:耳罩式耳机纯音基准等效阈声压级
- GB/T 3091-2015低压流体输送用焊接钢管
- GB/T 1796.7-2018轮胎气门嘴第7部分:零部件
- 分光计的使用与调节-课件
- 新概念英语入门级AUnit3课件
评论
0/150
提交评论