A Road Map Through Nachos——Nachos machine

来源:互联网 发布:qt抽奖软件 编辑:程序博客网 时间:2024/06/10 17:29
Nachos Machine
    Nachos simulates a machine that roughly approximates the MIPS architecture. The machine has registers, memory and a cpu.
    Nachos模拟了一个与MIPS架构大致接近的机器。该机器拥有寄存器,内存以及处理器。
    In addition, an event-driven simulated clock provides a mechanism to schedule interrupts and execute them at a later time.
    除此之外,一个事件驱动的模拟时钟提供了安排中断并在一段时间后执行的机制。
    The simulated MIPS machine can execute arbitrary programs.
    用于模拟的MIPS机器可以执行任意的程序。
    One simply loads instructions into the machine's memory, initializes registers (including the program counter PCReg) and then tells the machine to start executing instructions.
    将程序的指令加载进机器的内存,初始化寄存器(包括程序计数器PCReg)并通知机器开始执行指令。
    The machine then fetches the instruction PCReg points at, decodes it, and executes it.
    然后机器从PCReg中取出指令,对指令进行解码并运行指令。
    The process is repeated indefinitely, until an illegal operation is performed or a hardware interrupt is generated.
    处理器一直重复着取指令-执行循环直到发现了一条非法指令或产生一个硬件中断。
    When a trap or interrupt takes place, execution of MIPS instructions is suspended, and a Nachos interrupt service routine is invoked to deal with the condition.
    当一个自陷或中断发生时,将挂起执行MIPS指令,Nachos将调用中断服务例程来对相应的情况进行处理。
    
    Conceptually, Nachos has two modes of execution, one of which is the MIPS simulator.
    概念上,Nachos有两种运行模式,其中一种是MIPS模拟器。
    Nachos executes user-level processes by loading them into the simulator's memory, initializing the simulator's registers and then running the simulator.
    Nachos运行用户级进程时是将它们加载到模拟器的内存,初始化模拟器器的寄存器并运行模拟器。
    User-programs can only access the memory associated with the simulated machine.
    用户程序只能访问与模拟机器相关联的内存。
    The second mode corresponds to the Nachos ``kernel.''
    第二种模式与Nachos的“内核”相关。
    The kernel executes when Nachos first starts up, or when a user-program executes an instruction that causes a hardware trap (e.g., illegal instruction, page fault, system call, etc.).
    当Nachos启动或当用户程序执行一条指令并引起硬件自陷(如:非法指令,缺页错误,系统调用等)时执行内核。
    In ``kernel mode'', Nachos executes the way normal Unix processes execute.
    在“内核模式”下,Nachos运行就与Unix进程的运行相类似。
    That is, the statements corresponding to the Nachos source code are executed, and the memory accessed corresponds to the memory assigned to Nachos variables.
    也就是说,Nachos的源码被执行,内存的访问与分配给Nachos变量的内存相对应。
    
Machine Components
    The Nachos/MIPS machine is implemented by the Machine object, an instance of which is created when Nachos first starts up.The Machine object exports a number of operations and public variables that the Nachos kernel accesses directly.
    Nachos/MIPS机器由Machine对象定义,当Nachos启动时将创建Machine对象的一个实例。该对象定义了一组Nachos内核可以直接访问的方法和公共变量。
    The Nachos Machine object provides registers, physical memory, virtual memory support as well as operations to run the machine or examine its current state.
    Nachos机器对象提供寄存器,物理内容,虚拟内存的支持,同时也包括启动机器和检查机器状态的操作。
    When Nachos first starts up, it creates an instance of the Machine object and makes it available through the global variable machine.
    当Nachos启动时,创建了Machine对象的实例并可以通过全局变量machine进行访问。
    The following public variables are accessible to the Nachos kernel: registers, mainMemory, virtual memory.
    register, mainMemory, virtual memory这些公共的变量可以从Nachos内核中进行访问。
    
    At this point, we know enough about the Machine object to explain how it executes arbitrary user programs.
    从以上几点,我们已经了解了Machine对象并可以解释它如何执行任意的用户程序。
    First, we load the program's instructions into the machine's physical memory .
    首先,我们加载用户程序的指令到机器的物理内存。
    Next, we initialize the machine's page tables and registers.
    接下来,我们初始化机器的页表以及寄存器。
    Finally we invoke machine->Run(), which begins the fetch-execute cycle for the machine.
    最后,我们调用machine对象的Run方法,通过该方法开始执行机器的fetch-execute(取指令-执行)循环。
    
    The following public variables are accessible to the Nachos kernel:
    Nachos内核可以访问的公共变量:
    registers:
        An array of 40 registers, which include such special registers as a stack pointer, a double register for multiplication results, a program counter, a next program counter (for branch delays), a register target for delayed loads, a value to be loaded on a delayed load, and the bad virtual address after a translation fault.
        一个包含40个寄存器的数组,包括一些特殊寄存器像栈指针,双寄存器用于存放乘法操作的结果,程序计数器,下一个程序计数器(用于分支延迟),用于延迟加载的目标寄存器,用于保存延迟加载值的寄存器和地址变换失败后用于保存无效虚拟地址的寄存器。
    mainMemory:
        Memory is byte-addressable and organized into 128-byte pages, the same size as disk sectors.
        内存是按字节编址并以每页128字节进行组织,内存中的每页的大小与磁盘每扇区的大小一致。
        Memory corresponding to physical address x can be accessed in Nachos at machine->mainMemory[x]. By default, the Nachos MIPS machine has 31 pages of physical memory.
        内存中物理地址x可以在Nachos中通过machine->mainMemory[x]进行访问。缺省情况下,Nachos MIPS机器有31页。
    Virtual Memory:
        Nachos supports VM through either a single linear page table or a software-managed TLB (though not simultaneously).
        Nachos通过单线性页表或软件管理的TLB(两者并不同时支持)来支持虚拟内存。
    Operations:
    操作:
        Machine(bool debug):
            The Machine constructor takes a single argument debug.
            Machine对象的构造器
            When debug is TRUE, the MIPS simulator executes instructions in single step mode, invoking the debugger after each instruction is executed.
            当传入的参数debug为True时,MIPS模拟器以单步模式来运行指令,当每条指令执行完成时调用调试器。
            By default, single-stepping is disabled. It is enabled by specifying the ``-s'' command line option when starting Nachos up.
            缺省情况下,单步模式是禁用的。你可以在启动Nachos时指定“-s”参数开启该功能。
        ExceptionType Translate(int virtAddr, int* physAddr, int size, bool writing):
            converts virtual address virtAddr into its corresponding physical address physAddr.
            将虚拟地址virtAddr转化为相应的物理地址physAddr。
        OneInstruction():
            does the actual work of executing an instruction.
            执行一条机器指令。
            It fetches the current instruction address from the PC register, fetches it from memory, decodes it, and finally executes it.
            从程序计数器中取得当前的指令地址,再从内存中取中将要执行的指令,解码指令,最后运行指令。
            Any addresses referenced as part of the fetch/execute cycle (including the instruction address given by PCReg) are translated into physical addresses via the Translate() routine before physical memory is actually accessed.
            在取指令-执行循环中的每一个地址(包括PCReg中给出的指令地址)都需要通过Tranlate()在物理地址可访问之前将其转化成物理地址。
        Run():
            ``turns on'' the MIPS machine, initiating the fetch-execute cycle. This routine should only be called after machine registers and memory have been properly initialized.It simply enters an infinite fetch-execute loop.
            打开MIPS机器,初始化取指令-执行循环。该方法只有在机器寄存器和内存初始化后才能被调用。其中只是进入一个无限的取指令-执行循环。
            
            The main loop in Run does three things:
            主循环完成三件事:
                1) it invokes OneInstruction to actually execute one instruction
                1)调用OneInstruction执行一条指令
                2) it invokes the debugger, if the user has requested single-step mode on the command line
                2)如果用户开启的单步调试功能,调用调试器,
                3) it increments a simulated clock after each instruction.
                3)在每条指令执行完成后增加模拟时钟的计数
        int  ReadRegister(int num):
            fetches the value stored in register num.
            取寄存器中的值。
        void WriteRegister(int num, int value):
            places value into register num.
            将一个值写入到寄存器中。
        bool ReadMem(int addr, int size, int* value):
            Retrieves 1, 2, or 4 bytes of memory at virtual address addr.
            从虚拟地址addr中获取内存的1、2或4字节。
            Note that addr is the virtual address of the currently executing user-level program; ReadMem invokes Translate before it accesses physical memory.
            注:参数中的addr是当前运行用户程序的虚拟地址,ReadMem在访问物理地址之前调用Tranlate进行地址转化。
            One point that should be noted is that ReadMem fails (returning FALSE), if the address translation fails (for whatever reason).
            需要注意的是当地址转化失败(任何原因)该方法返回False。
            Thus, if the page is not present in physical memory, ReadMem fails. ReadMem does not distinguish temporary failures (e.g., page not in memory) from hard errors (e.g., invalid virtual address)
            同时,如果所需的页不在内存中时也会调用失败。该方法返回FALSE时并不区分错误是由临时错误(如,缺页错误)或物理错误(如:不可用的虚拟地址)所引发。
        bool WriteMem(int addr, int size, int value):
            writes 1, 2, or 4 bytes of value into memory at virtual address addr. The same warnings given for ReadMem apply here as well.
            将参数value的1、2或4字节写入到虚拟地址addr对应的内存。需要注意的问题与ReadMem相类似。

Interrupt Management
中断管理
    Nachos simulates interrupts by maintaining an event queue together with a simulated clock.
    Nachos通过管理一个事件队列以及模拟时钟来模拟中断。
    As the clock ticks, the event queue is examined to find events scheduled to take place now.
    当时钟每滴答一次时,将查看事件队列并查找是否有已安排的事件需要在该时钟周期内执行。
    The clock is maintained entirely in software and ticks under the following conditions:
    时钟完全的由软件进行控制并在以下情况时发生改变:
        Every time interrupts are restored (and the restored interrupt mask has interrupts enabled), the clock advances one tick. Nachos code frequently disables and restores interrupts for mutual exclusion purposes by making explicit calls to interrupt::SetLevel().
        每当中断被恢复时(并且被恢复的中断掩码设置了允许中断),增加一个时钟滴答。Nachos代码中经常为了互斥而通过显式的调用interrupt::SetLevel()来禁用和恢复中断。
        Whenever the MIPS simulator executes one instruction, the clock advances one tick.
        每当MIPS模拟器执行完成一条指令时,增加一个时钟滴答。
        Whenever the ready list is empty, the clock advances however many ticks are needed to fast-forward the current time to that of the next scheduled event.
        当准备好队列为空时,将增加多个时钟滴答以达到从当前时间快速向前到达下一个安排好的事件。
    
    Whenever the clock advances, the event queue is examined and any pending interrupt events are serviced by invoking the procedure associated with the timer event (e.g., the interrupt service routine).
    当时钟增加时,将检查事件队列并且任何挂起的中断事件将通过调用与时钟事件相关联的例程来进行处理。
    All interrupt service routines are run with interrupts disabled, and the interrupt service routine may not re-enable them.
    所有的中断服务例程都要运行禁用中断并且不会重新开启允许中断。
    
    Warning: in interrupt handler may not call any routines that lead to a context switch of the current thread (e.g., scheduler::Run() or SWITCH() ). Doing so may lead to deadlock.     
    警告:在中断例程处理中将不可以调用任何可以引起当前线程进行上下文切换的例程(如:scheduler::Run() or SWITCH())。如果这样做会引发死锁。
    
    Operations:
    操作:
        void Schedule(VoidFunctionPtr handler, int arg, int when, IntType type):
            schedules a future event to take place at time when. When it is time for the scheduled event to take place, Nachos calls the routine handler with the single argument arg.
            安排一个在时间when时将执行的未来事件。当已安排的事件到达运行时间时,Nachos将调用处理例程并传递参数arg。
        IntStatus SetLevel(IntStatus level):
            Change the interrupt mask to level, returning the previous value. This routine is used to temporarily disable and re-enable interrupts for mutual exclusion purposes.
            改变中断掩码到level对应的值,并返回前一个中断掩码。该例程用于为了互斥操作而临时的禁用或启用中断。
        OneTick():
            advances the clock one tick and services any pending requests (by calling CheckIfDue).
            增加一个时钟滴答并且服务任一个挂起的请求(通过调用CheckIfDue)。
            It is called from machine::Run() after each user-level instruction is executed, as well as by SetLevel when the interrupts are restored.
            该方法在machine::Run()中当每个用户级的指令被执行后,也在SetLevel中当中断被恢复时调用,
        bool CheckIfDue(bool advanceClock):
            examines the event queue for events that need servicing now. If it finds any, it services them. It is invoked in such places as OneTick.
            检查当前事件队列中是否有需要服务的事件。如果找到了一个事件,将为其提供服务。在像OneTick之类的方法中调用。
        Idle():
            ``advances'' to the clock to the time of the next scheduled event.
            增加时钟滴答到下一个已安排的事件滴答。
            It is called by the scheduler (actually Sleep()) when there are no more threads on the ready list and we want to ``fast-forward'' the time.
            由安排器(实际上Sleep())进行调用,当没有任何线程在准备好队列时我们需要时间”快速向前”。

Real-Time Clock Interrupts
    Nachos provides a Timer object that simulates a real time clock, generating interrupts at regular intervals.
    Nachos提供了Timer对象来模拟一个真实的时钟,用于在定期的间隔内产生中断。
    
    Operations:
    操作:
        Timer(VoidFunctionPtr timerHandler, int callArg, bool doRandom):
            The Timer constructor creates a real-time clock that interrupts every TimerTicks (100) time units.
            Timer对象的构造器用来创建一个实时的时钟,每100个计时器滴答后产生中断。
            When the timer goes off, the Nachos simulator invokes procedure timerHandler, passing it callArg as an argument.
            当计时器到达后,Nachos模拟器调用例程timerHandler并将callArg作为其参数。
            To add a bit of non-determinism to the system, argument doRandom specifies that the time between interrupts should be taken from a uniform interval between 1 and 2*TimerTicks.
            为了在系统中增加一点非确定性,参数doRandom指定产生中断的时间间隔将在1和2*TimerTicks之间随机生成。
            The real-time clock can be used to provide preemption.
            实时的时钟将被用于提供抢占。
    
    Note that starting Nachos with the ``-rs'' option creates a timer object that interrupts at random intervals and preempts the currently running thread.
    注:当启动Nachos时提供“-rs”参数将生成一个timer对象,在随机的时间间隔内产生中断并抢占当前正在运行的线程。

Address Translation
地址转换
    Nachos supports two types of VM architectures: linear page tables, or a software managed TLB. Nachos supports one or the other, but not both (simultaneously).  
    Nachos提供了两种虚拟内存框架:线性页表和软件管理的TLB。Nachos运行时只支持其中一种并不能同时支持。
    
    Linear Page Tables
    线性页表
        With linear tables, the MMU splits a virtual address into page number and page offset components.
        使用线性表,存储器管理单元(MMU——Memory Management Unit)将虚拟地址分隔成页号和页内偏移量。
        The page number is used to index into an array of page table entries.
        页号用于作为页表的索引
        The actual physical address is the concatenation of the page frame number in the page table entry and the page offset of the virtual address.
        实际的物理地址是由以页号为索引的页表内容加上虚拟地址中指定的页内偏移量。
        
        To use linear page tables, one simply initializes variable machine->pageTable to point to the page table used to perform translations.
        为了使用线性页表,一个简单的初始化变量machine->pageTable将指向用于转换的页表。
        In general, each user process will have its own private page table. Thus, a process switch requires updating the pageTable variable.
        通常情况下,每个用户都有自己私有的页表。因此,当进程切换时需要更新pageTable变量。
        In a real machine, pageTable would correspond to a special register that would be saved and restored as part of the SWITCH() operation.
        在实际机器中,页表通常由特殊的寄存器指定并在SWITCH()操作时进行保存和恢复。
        The machine variable pageTableSize indicates the actual size of the page table.
        machine对象的pageTableSize变量用于指定页表的实际大小。
        
        Page table entries consist of:
        页表项的组成:
            the physical page frame number for the corresponding virtual page
            与虚拟页对应的物理内存页帧号
            a flag indicating whether the entry is currently valid (set by the OS, inspected by hardware)
            一个标识指示当前表项是否可用(操作系统设置,硬件负责检查)
            a flag indicating whether the page may be written (set by OS, inspected by hardware)
            一个标识指示当前物理页是否可写(操作系统设置,硬件负责检查)
            a bit indicating whether the page has been referenced (set by the hardware, inspected and cleared by OS)
            一个比特指示是否当前页有相关的引用(硬件设置,操作系统负责检查和清除)
            a dirty bit (set by hardware, inspected and cleared by OS)
            一个脏比特(硬件设置,操作系统负责检查和清除)
            
        The Nachos machine has NumPhysPages of physical memory starting at location mainMemory.
        Nachos机器在物理内存从mainMemory开始有NumPhysPages个页。
        Thus, page 0 starts at machine->mainMemory, while page N starts at mainMemory+N*PageSize.
        因此,页0从machine->mainMemory,页N从mainMemory+N*PageSize开始。
    Software Managed TLB:
    软件管理的TLB
        ......
        
Console Device
控制台设备
    Nachos provides a terminal console device and a single disk device.
    Nachos提供一个终端控制台设备和一个单磁盘设备。
    Nachos devices are accessed through low-level primitives that simply initiate an I/O operation.
    Nachos设备通过底层的原语简单的初始化一个I/O操作进行访问。
    The operation itself is performed later, with an ``operation complete'' interrupt notifying Nachos when the operation has completed.
    操作本身被执行后,当完成操作后将有一个“操作完成”的中断通知给Nachos。
    The Console class simulates the behavior of a character-oriented CRT device.
    Console类模拟了一个面向字符的CRT设备的行为。
    Data can be written to the device one character at a time through the PutChar() routine.
    数据可以通过PutChar()例程一次将一个字符写入到设备。
    When a character has successfully been transmitted, a ``transmit complete'' interrupt takes place and the user-supplied handler is invoked.
    当字符传输成功后,将引发一个“传输完成”中断并调用用户提供的处理例程。
    The interrupt handler presumably checks if more characters are waiting to be output, invoking PutChar again if appropriate.
    中断处理器会检查是否有更多的字符在等待输出,如果有将再次调用PutChar。
    When a new character arrives, the console device generates an interrupt and the user-supplied input interrupt service routine is invoked to retrieve the character from the device and (presumably) place it into a buffer from which higher-level routines (e.g., GetChar()) can retrieve it later.
    当有一个新的字符到达时,控制台设备会产生一个中断,调用用户提供的中断处理例程从设备获取字符并(可能的)将字符保存到缓存中以便高层例程(如:GetChar())在以后获取。
    
    Operations:
    操作:
        Console(char *readFile, char *writeFile, VoidFunctionPtr readAvail, VoidFunctionPtr writeDone, int callArg):
            The constructor creates an instance of a terminal console.
            创建一个终端控制台实例的构造器。
            Argument readFile contains the Unix file name of where the data is to be read from; if NULL, standard input is assumed.
            参数readFile包括一个从中读出数据的Unix文件名,如果为NULL,则设置为标准输入。
            Argument writeFile indicates where output written to the console is to go; if NULL, standard output is assumed.
            参数writeFile指示写入到控制台的输出的位置,如果为NULL,则设置为标准输出。
            
            When a character becomes available for reading, readAvail is invoked with an argument of callArg to notify the Nachos that a character is available.
            如果有字符可以被读取时,将以参数callArg调用readAvail并通知Nachos有字符可以被读取。
            The character itself is retrieved by calling Console::GetChar().
            字符本身通过调用Console::GetChar()来获取。
            Upon return, it is assumed that the character has been retrieved and when the next one arrives, readAvail will be called again.
            当其返回后就假定字符已经被读取并在下一个字符到来后,再次调用readAvail。
        void PutChar(char ch):
            Writes character ch to the output device.
            将字符ch写入到输出设备。
            Once output has started, it is an error to invoke PutChar() again before the corresponding I/O complete interrupt has taken place.
            将输出开始后并在相应的I/O操作完成中断发生前再次调用PutChar是错误的。
            Once the console device has written the character to the device, it invokes the user-supplied procedure writeDone , passing it callArg as an argument.
            一旦控制台设备完成将字符写入到设置后,将以参数callArg调用用户提供的例程writeDone。
        char GetChar():
            Retrieves a character from the console.
            从控制台获取一个字符。
            GetChar returns EOF if no new data is available.
            GetChar将返回EOF如果没有新的可读取的数据。
            Normally, the user would not invoke GetChar unless the availability of new data had first been signalled via the readAvail() interrupt service routine.
            通常情况下,用户将不会调用GetChar除非新数据的可用性已经通过readAvail()中断处理例程进行了标记。
        void CheckCharAvail():
            an internal procedure used to see if new data is available for reading.
            一个内部的例程用于查看是否有新的数据可以被读取。
    
    When a console device is created by the constructor, the appropriate Unix files (or stdin/stdout) are opened and a timer event is scheduled to take place 100 time units in the future.
    当一个控制台设备被构造器创建后,合适的Unix文件(或标准输入/输出)已被打开并且安排了一个在未来100滴答后启动的计时器事件。
    When the timer expires, the routine CheckCharAvail is invoked to see if any data is present.
    当计时器到达时间后,例程CheckCharAvail将被调用来查看是否有任何可用的数据。
    If so, CheckCharAvail reads that character and invokes the user-supplied input interrupt handler readAvail.It then schedules a new timer event so that the process repeats every 100 time units.
    如果有可用的数据,CheckCharAvail读取相应的字符并调用用户提供的输入中断处理例程readAvail。然后再安排一个新计时器事件以便该处理每100滴答重复的进行。
    CheckCharAvail simply polls every 100 clock ticks for new data, calling the interrupt service routine whenever data is present for processing.
    在每100个时钟滴答时调用CheckCharAvail用于获得新数据,调用中断处理例程对数据进行处理。
    
    Device output is initiated by calling PutChar, giving it a single character to output.
    设备输出通过调用PutChar来初始化,给其需要输出的字符。
    Once character output has been initiated, the device is made busy until the output complete interrupt takes place.
    当字符输出被初始化后,直到输出完成中断发生之前,该设备都处于忙状态。
    PutChar simply outputs the one character, sets an internal flag to indicate that the device is busy, and then schedules a timer interrupt to take place 100 clock ticks later.
    PutChar只是简单的输出一个字符并设置一个内部标识指示设备忙,并且安排一个在未来100滴答后启动的计时器事件。
    When the timer expires, the state of the device is changed from busy to idle, and the user-supplied output interrupt complete routine is invoked.
    当计时器到达时间后,将设备的状态从忙改变为空闲并调用用户提供的输出中断完成例程。
    This routine would presumably invoke PutChar if additional output characters were queued awaiting output.
    如果仍有在队列中等待输出的字符则将再次调用PutChar。

Disk Device
磁盘设备
    The Disk object simulates the behavior of a real disk. The disk has only a single platter, with multiple tracks containing individual sectors.
    Disk对象用于模拟一个真实磁盘的行为。该磁盘只一个盘片,多个轨道包含独立的扇区。
    Each track contains the same number of sectors, and blocks are uniquely identified by their sector number.
    每个磁轨包含相同数量的扇区,每一块都由其扇区号进行唯一的标识。
    As with a real disk, the OS initiates operations to read or write a specific sector, and a later interrupt indicates when the operation has actually completed.
    对于真实的磁盘,操作系统负责初始化对特定的扇区读/写操作,当操作完成后将有一个中断对其进行指示。
    The Nachos disk allows only one pending operation at a time; the OS may initiate new operations only when the device is idle.
    Nachos磁盘在某一时间只允许一个挂起的操作,只有在磁盘设备空闲时操作系统才会初始化一个新的操作。
    Note that it is the responsibility of the OS to insure that new requests are not issued while the disk is busy servicing an earlier request.
    注:操作系统负责确保当磁盘在忙于处理前一个请求时,新的请求不会对其产生影响。
    In order to simulate typical delays in accessing a disk, the Nachos Disk object dynamically varies the time between the initiation of an I/O operation and its corresponding I/O complete interrupt.
    为了模拟在访问磁盘时的延迟,Nachos Disk对象在初始化I/O操作和与之对应的I/O完成中断之间使用不同的动态时间。
    
    The simulated disk contains NumTracks (32) tracks, each containing SectorsPerTrack (32) sectors. Individual sectors are SectorSize (128) bytes in size.
    模拟的磁盘包含NumTracks(32)个磁轨,每个磁轨包含SectorsPerTrack(32)个扇区。每个扇区大小为SectorSize(128)字节。
    In addition, Disk contains a ``track buffer'' cache.
    除此之外,磁盘还包括一个“磁轨缓冲区”缓存
    Immediately after seeking to a new track, the disk starts reading sectors, placing them in the track buffer.
    当找到一个新的磁轨后,磁盘立即开始读取扇区并将它们保存到磁轨缓冲区。
    That way, a subsequent read request may find the data already in the cache reducing access latency.
    通过这种方法,在随后的读取请求时可能发现需要的数据已经存在于缓存中,这样可以减小访问延迟。
    
    Operations:
    操作:
        Disk(char *name, VoidFunctionPtr callWhenDone, int callArg):
            This constructor assumes that the simulated disk is kept in the Unix file called name.
            该构造器假设需要模拟的磁盘保存在一个名为name的Unix文件中。
            If the file does not already exist, Nachos creates it and writes a ``magic number'' of 0x456789ab into the initial four bytes.
            如果该文件还未存在,Nachos将创建它并将一个等于0x456789ab的魔数写入到该文件的前四个字节。
            The presence of a magic number allows Nachos to distinguish a file containing a Nachos simulated disk from one containing something else.
            魔数的存在允许Nachos将一个Nachos的模拟磁盘文件与其它文件区分开来。
            Finally, Nachos insures that the rest of the file contains NULL sectors.
            最后,Nachos确保文件的剩余部分包含NULL扇区。
            All Nachos disks have the same size, given by the formula NumSectors*SectorsPerTrack
            所有的Nachos的磁盘都有相同的大小,通过NumSectors*SectorsPerTrack公式进行计算
            
            If the file already exists, Nachos reads the first 4 bytes to verify that they contain the expected Nachos ``magic number,'' terminating if the check fails.
            如果文件已经存在,Nachos读取该文件的前4个字节验证是否包含Nachos所期望的魔数,如果验证失败则操作中止。
            
            The last two constructor arguments are used to provide an ``I/O complete'' interrupt mechanism.
            最后两个参数用于提供“I/O完成”的中断机制。
            the Nachos machine signals the completion of a Disk operation (e.g., read or write) by invoking the procedure callWhenDone, passing it an argument of callArg.
            Nachos机器通过以callArg参数调用callWhenDone例程来产生一个磁盘操作完成的信号。
            the SynchDisk object uses this routine to wake up a thread that has been suspended while waiting for I/O to complete.
            SynchDisk对象使用该例程来唤醒一个因为等待I/O操作完成而被挂起的线程。
        ReadRequest(int sectorNumber, char *data):
            Is invoked to read the specified sector number into the buffer data. In Nachos, all sectors are the same size (SectorSize).
            将指定扇区的内容读取到缓冲数据区。在Nachos中,所有的扇区都有相同的大小(SectorSize)。
            
            Note that this operations returns immediately, before the transfer actually takes place.
            注:该调用在传输真正开始前立即返回。(异步调用)
            ReadRequest schedules an interrupt to take place sometime in the future, after a time roughly dependent on the seek distance needed to complete the operation.
            ReadRequest安排一个以未来时间将发生的一个中断,该时间依赖于完成操作所需查找的距离。
            Only after the interrupt takes place is it correct to start using the data.
            只有在中断发生后才能正确的开始使用数据。
        WriteRequest(int sectorNumber, char *data):
            Similar to ReadRequest, except that it writes a single sector.
            与ReadRequest相类似,除了是将缓冲区数据写入到一个扇区。
        ComputeLatency(int newSector, bool writing):
            estimates the latency required to access the block newSector given the current position of the disk head.
            估算从当前磁盘头到访问新扇区所需的延迟。
            The routine is used in deciding when to schedule an I/O complete interrupt when servicing a read or write request.

            这个例程用于当处理一个读/写请求时,决定何时应安排一个I/O完成中断。