nachos介绍

实验目的

深入理解计算机操作系统,对上学期操作系统知识进行复习回顾,同时理解操作系统在实际中的应用。对线程(包括同步、信号量、调度)、文件系统(包括分页、文件创建等操作)有进一步的理解和认识。

nachos介绍

Nachos的全称是“Not Another Completely Heuristic Operating System”,它是一个可修改和跟踪的操作系统教学软件。它给出了一个支持多线程和虚拟存储的操作系统骨架,可让学生在较短的时间内对操作系统中的基本原理和核心算法有一个全面和完整的了解。

nachos系统及部分源码分析

  • Nachoes 包整体分析:

nachos.ag 包提供了能够自动分层 nachoes 项目的类;
nachoes.machine 包提供了实现 nachoes 虚拟机的类;
nachoes.security 包主要是用来保护 nachoes 的内核不受到破坏;
nachoes.thread 包主要提供了用来实现 nachoes 多线程内核的类;
nachoes.userprog 包主要是提供了允许 nachoes 在单独的地址空间中加载和执行单线程用户程序的一些类;
nachoes.vm 主要是用来让 nachoes 运行的进程按需求分页,利用一些硬件 TLB 来地址上的一些转换。

  • nachos线程:

一个KThread对象代表一个Nachos线程,线程级的概念与操作,是在KThread类中体现的,如:
线程的创建 (KThread.fork())
线程的就绪(KThread.ready())
线程的睡眠(KThread.sleep())
线程的状态与转换
线程的上下文切换(sleep和yield可引起)
一个Nachos线程由三部分组成,一个KThread对象,与Kthread对象对应的TCB对象,与TCB对象绑定的Java 线程。java thread、TCB对象、KThread对象之间是一一映射关系。
关于Nachos线程的创建
KThread NachosThread=new KThread(new KThreadTarget);
NachosThread.fork();
KThreadTarget是一个Runnable对象,其run()中代码是子线程的执行体。

  • KThread主要方法及功能解析:

    currentThread():静态方法,实现返回当前KThread类型线程的操作。
    KThread():构造方法。实现判断当前线程是否为空。如果currentThread不为空,则分配一个新的TCB空间;否则,该方法会创建一个新的线程等待队列,将新线程加入等待队列中,将新线程设为当前线程,将tcb指向当前TCB空间,并修改新线程的状态(会由等待改变为运行状态),检查toBeDestory值等一系列线程运行前的准备工作。
    KThread(Runnabletarget):构造方法,创建一个新的KThread,并传递给它一个对应的java线程。
    setTarget(Runnabletarget):为KThread设置要运行它的对应的java线程。
    fork():创建线程的方法。先运行关中断操作,然后对应的tcb启动一个java线程,调用runThread方法,然后将其加入等待队列中。
    runThread():线程运行。先调用begin()方法,然后让KThread对应的java线程run()方法,最后调用finish()方法,结束线程。
    begin():调用了restoreState()方法,该方法实现了KTread运行前的一系列准备工作。
    finish():该方法实现了当当前线程运行完成后,将等待队列中下一个线程拿出。
    yield():静态方法,将当前线程加入等待队列,引起调度。
    sleep():静态方法,拿出等待队列中的下一个进程即将运行,将当前线程进入等待队列中,引起调度。
    ready():设置当前线程状态为等待,加入就绪队列。
    creatIdleThread()方法:创建一个闲逛线程,永远不会被阻塞,只有当其他所有线阻塞时才运行,永远不会被加入到等待队列。
    runNextThread()方法:取出等待队列中的下一个线程并使其运行。
    run()方法:先将当前线程加入就绪队列,调用savaState方法,准备放弃CPU。调用run方法的线程设为当前线程,tcb进行上下文切换,调用resoreState方法,使当前线程做运行前的准备工作。

  • nachos中锁的使用:

nachos中提供锁,以实现同步等。

Lock类主要方法如下:
acquire():若当前线程没有持有锁,可原子地得到锁。关中断。如果锁持有者不为空,则将当前线程加入waitQueue,否则取出当前线程让他得到锁。开中断。
release():释放锁,即让waitQueue里的下一个线程得到锁,并将其加入等待队列。
isHeldByCurrentThread():判断当前线程是否持有锁。

  • nachos中的中断系统:

nachos在初始化时会创建interrupt controller(中断控制器),对外部提供开关中断的接口,供其它程序调用,保证程序原子性。
外部程序可以调用中断控制器提供的接口开关中断(disable()与enable())
当为一个设备设置中断时,可在该设备的类中调用Interrupt.schedule(),该方法需要三个参数 (when:该中断何时到期可以响应;type: 中断类型;handler: 响应该中断时执行的中断处理程序)。
nachos的中断不是实时响应,而是在设置中断时提供一个时间参数time,从设置中断开始的time时刻后,该中断到期,可以响应该中断。
开关中断操作:
开中断:
public boolean enable() { setStatus(true); }
关中断:
public boolean disable() {setStatus(false); }
Nachos中断控制器模拟了一个时钟,该时钟从nachos启动时开始计数(ticks),作为nachos的系统时间。当nachos模拟的CPU执行完一条指令,ticks=ticks+1,当中断状态从disabled转到enabled,ticks+10 。系统调用 checkIfDue 来执行中断查询,在hander中安排调度。
涉及类:
Machine.Interrupt
模仿底层的中断硬件,提供了方法setStatus,来设置能够或不能够中断。记录所有硬件设备可能引起的行为将发生的中断和什么时间他们可能出现。这个模块也记录模拟的节拍,下面情况发生时节拍增长:
之前是关中断,开了中断后+10;每秒百万条指令已经执行后+1。
中断(包括时间片上下文切换)不可以出现在开中断时的任何代码处。但只在模拟节拍前进时可以,以便它可以成为模拟硬件的节拍来调用中断控制。这意味着错误的同步代码可以在这个模拟硬件上运行(甚至在随意的时间片),但是却不能在真正的硬件上运行。即使nachos不能一直察觉到你的程序在现实中是错的,你也应该写正确的同步代码。
Machine.Timer
该类是计时器类,控制着系统时间和计时器中断。其核心是Timer.scheduleInterrupt(),与 Timer.timerInterrupt()相互作用维持计时器中断。Timer.scheduleInterrupt()中获取Status.TimerTicks 来安排未来的调度时间(也就是调度间隔)并利用随机数制造调度时间的不稳定性(0~25),当 timerInterrput()被执行,会再次执行 Timer.scheduleInterrupt()安排下次的调度,而 timerInterrrput()中会执行 Timer.handler 的 run 方法,这个handler 是由 setHandler 传入的定时器中断。至于 AutoGraderInterrupt,虽然 delay为 1,但是由于其 scheduleInterrupt 安排在 timerIntterupt 中,也是每 Stats.TimerTicks执行一次,该中断处理程序会对权限进行检查,保证调度器有权限来调度。

  • nachos中的文件系统:

Nachos 文件系统都实现了 FileSystem 接口,提供打开文件和删除文件的方法。所有的文件都要实现 OpenFile 类,作为文件系统返回的文件。OpenFile 定义了Nachos的一个文件及对文件的相关操作,类似于Java中的File类。
Nachos系统利用java的File实现nachos文件系统的open(), remove(), read(), write(), close()具体实现。

Userprocess类:包括一个用户进程,一个文件表,以及有关正在执行的程序的信息。
execute方法方法:根据文件名和参数,用指定的参数来执行可执行文件。
readVirtualMemoryString方法:从进程的虚拟内存中读取内容并转化成字符串的格式。
intreadVirtualMemor方法:将该进程的虚拟内存中的数据传到指定的数组中。

Userkernel类:继承自ThreadedKernel类,实现一个内核支持多个用户进程,(实现多道程序设计。)
Initialize初始化一个内核,创建一个同步控制台;selftest()进行自检,控制台是否运行正常;UserProcesscurrentProcess()用来获得当前进程;run()方法是通过创造一个进程或是在里面运行一个脚本程序来开始运行用户程序,而这个必须通过运行的脚本程序的名字是靠Machine.getShellProgramName()返回的;terminate()方法就是用来停止内核不返回。

SynchConsole类:为机器的控制台提供一个简单的同步的接口,而这个接口也可以被OpenFile的对象访问。