User-Level Processes
使用者級進程
Nachos runs user programs in their own private address space.
Nachos運行使用者程式在其私人的地址空間。
Nachos can run any MIPS binary, assuming that it restricts itself to only making system calls that Nachos understands.
Nachos可以運行任何MIPS二進位檔案並假設使用者程式只使用了Nachos可以理解的系統調用。
In Unix, ``a.out'' files are stored in ``coff'' format. Nachos requires that executables be in the simpler ``Noff'' format.To convert binaries of one format to the other, use the coff2noff program.
在Unix中,“a.out”檔案以“coff”格式進行儲存。Nachos需要以“Noff”格式進行運行。使用coff2noff程式將“coff”格式轉化為“Noff”格式。
Noff-format files consist of four parts. The first part, the Noff header, describes the contents of the rest of the file, giving information about the program's instructions, initialized variables and uninitialized variables.
Noff格式檔案包括四個部分。第一個部分為Noff頭用於描述檔案其它部分的內容。包括程式運行指令,初始化或未初始化的變數。
The Noff header resides at the very start of the file and contains pointers to the remaining sections. Specifically, the Noff header contains:
Noff頭在檔案的開始處並包括指向剩餘節的指標。特別的,noff頭還包括:
noffMagic:
A reserved ``magic'' number that indicates that the file is in Noff format. The magic number is stored in the first four bytes of the file.
一個保留的魔數用於指示該檔案是Noff格式。該魔數儲存在檔案的前四個位元組。
Before attempting to execute a user-program, Nachos checks the magic number to be sure that the file about to be executed is actually a Nachos executable.
在嘗試運行一個使用者程式之前,Nachos檢查魔數以確保該檔案是Nachos可以執行的。
For each of the remaining sections, Nachos maintains the following information:
在剩餘的每個節中,Nachos管理著以下資訊:
virtualAddr:
虛擬位址:
What virtual address that segment begins at (normally zero).
每段開始的虛擬位址(通常從零開始)。
inFileAddr:
檔案中地址:
Pointer within the Noff file where that section actually begins (so that Nachos can read it into memory before execution begins).
指向檔案中段真正的開始地址(這樣可以在執行之前Nachos將其讀入到記憶體中)。
size:
大小:
The size (in bytes) of that segment.
在位元組為單位的段大小。
When executing a program, Nachos creates an address space and copies the contents of the instruction and initialized variable segments into the address space.
當開始執行一個程式,Nachos建立一個地址空間並拷貝運行檔案的指令及初始化的變數段到地址空間。
Note that the uninitialized variable section does not need to be read from the file.
註:未初始化的變數段並不需要從檔案中讀取。
Since it is defined to contain all zeros, Nachos simply allocates memory for it within the address space of the Nachos process and zeros it out.
因為其都是包含零,Nachos只是簡單的在地址空間中為其分配記憶體並將其初始化為零。
Process Creation
建立進程
Nachos processes are formed by creating an address space, allocating physical memory for the address space, loading the contents of the executable into physical memory, initializing registers and address translation tables, and then invoking machine::Run()
to start execution.
Nachos進程建立地址空間,為其分配實體記憶體,載入可執行指令到實體記憶體,初始化寄存器和地址轉換表,然後調用machine::Run()開始執行。
Run() simply ``turns on'' the simulated MIPS machine, having it enter an infinite loop that executes instructions one at a time).
Run()只是簡單的開啟類比的MIPS機器,當其進入到無限迴圈時開始執行程式指令。
Stock Nachos assumes that only a single user program exists at a given time.
Nachos假設在一個給定的時間只有一個使用者程式存在。
Thus, when an address space is created, Nachos assumes that no one else is using physical memory and simply zeros out all of physical memory (e.g., the mainMemory character array).
因此,當地址空間建立後,Nachos假設沒有其它的資源正在使用實體記憶體並將其初始化為零。
Nachos then reads the binary into physical memory starting at location mainMemory and initializes the translation tables to do a one-to-one mapping between virtual and physical addresses (e.g., so that any virtual address N maps directly into the physical
address N).
然後Nachos將二進位可執行檔讀入到從mainMemory開始的實體記憶體並初始化轉換表用於將虛擬位址與物理地址進行一對一的映射(如:任意虛擬位址N都映射到物理地址N)。
Initialization of registers consists of zeroing them all out, setting PCReg and NextPCReg to 0 and 4 respectively, and setting the stackpointer to the largest virtual address of the process (the stack grows downward towards the heap and text).
初始化寄存器包括將所有的寄存器都置零,設定PCReg和NextPCReg的值為零和4,設定棧指標指向進程的最大虛擬位址(棧是從高地址向低地址擴充)。
Nachos assumes that execution of user-programs begins at the first instruction in the text segment (e.g., virtual address 0).
Nachos假設使用者程式從text段的第一條指令開始執行(虛擬位址為零)。
When support for multiple user processes has been added, two other Nachos routines are necessary for process switching.
當支援多使用者進程時,兩個Nachos常式將需要進行進程切換。
Whenever the current processes is suspended (e.g., preempted or put to sleep), the scheduler invokes the routine AddrSpace::SaveUserState(), in order to properly save address-space related state that the low-level thread switching routines do not know about.
將當前進程被暫停(搶佔或讓其休眠),調度器將調用AddrSpace::SaveUserState()常式,為了合理的儲存與底層線程狀態相關的地址空間。
This becomes necessary when using virtual memory; when switching from one process to another, a new set of address translation tables needs to be loaded.
當使用虛擬記憶體時這一步是必須的,當從一個進程切換到另一個時,一組新的地址轉換表需要被載入。
The Nachos scheduler calls SaveUserState() whenever it is about to preempt one thread and switch to another.
Nachos調度器搶佔一個線程並切換到另一個時將調用SaveUserState()。
Likewise, before switching to a new thread, the Nachos scheduler invokes AddrSpace::RestoreUserState.
同樣的,在切換一個新線程之前,Nachos調度器調用AddrSpace::RestoreUserState。
RestoreUserState() insures that the proper address translation tables are loaded before execution resumes.
RestoreUserState()確保在恢複執行前合適的地址轉換表被載入。
Creating a Noff Binary
建立Noff二進位檔案
Nachos is capable of executing a program containing arbitrary MIPS instructions.
Nachos可運行任何包含MIPS指令的程式。
For example, C programs in the test directory are compiled using gcc on a MIPS machine to create ``.o'' files.
例如,在test目錄中的C程式使用MIPS機器的gcc編譯成“.o”檔案。
To create an a.out binary file, the loader prepends the instructions in test/start.s before the code of the user program.
要建立一個a.out二進位檔案,載入器將test/start.s中的指令加入到使用者程式的代碼之前。
File start.s contains initialization code that needs to be executed before the user's main program.
start.s檔案包括需要在使用者main程式之前啟動並執行初始化代碼。
Specifically, the very first instruction in start.s calls the user-supplied main routine, whereas the second instruction invokes the Nachos Exit system call, insuring that user processes terminate properly when their main program returns.
特別地,在start.s最前面的指令調用使用者提供的main常式,然而,第二個指令用於調用Nachos系統調用Exit來保證當使用者main返回時同時也中止使用者進程。
In addition, start.s contains stub modules for invoking system calls (described below).
除此之外,start.s還包括了調用系統調用的樁模組。
System Calls and Exception Handling
系統調用及異常處理
User programs invoke system calls by executing the MIPS ``syscall'' instruction, which generates a hardware trap into the Nachos kernel.
使用者程式通過執行MIPS的“syscall”指令來完成系統調用,該指令產生一個硬體自陷進入Nachos核心。
The Nachos/MIPS simulator implements traps by invoking the Routine RaiseException(), passing it a arguments indicating the exact cause of the trap.
Nachos/MIPS模擬器調用調用RaiseException()常式來申明一個自陷,調用時傳入參數用於指示什麼原因引發自陷。
RaiseException, in turn, calls ExceptionHandler to take care of the specific problem.
RaiseException將調用再轉給ExceptionHandler來處理具體的問題。
ExceptionHandler is passed a single argument indicating the precise cause of the trap.
ExceptionHandler調用時傳入參數用於指示引發自陷的具體原因。
The ``syscall'' instruction indicates a system call is requested, but doesn't indicate which system call to perform.
“syscall”指令指示了一個系統調用,便並不指示具體調用了何種系統調用。
By convention, user programs place the code indicating the particular system call desired in register r2 before executing the ``syscall'' instruction.
為了方便,使用者程式將在“syscall”指令之前將指示具體系統調用的代碼放置到r2寄存器中。
Additional arguments to the system call (when appropriate) can be found in registers r4-r7, following the standard C procedure call linkage conventions.
如果系統調用需要參數,則參數放置於下r4-r7寄存器,按標準的C調用機制進行放置。
Function (and system call) return values are expected to be in register r2 on return.
函數(和系統調用)的傳回值將放置在r2寄存器中。
Warning: When accessing user memory from within the exception handler (or within Nachos in general), user-level addresses cannot be referenced directly.
注意:當在異常處理(或Nachos代碼中)訪問使用者記憶體時,使用者級的地址不能直接引用。
Recall that user-level processes execute in their own private address spaces, which the kernel cannot reference directly.
因為使用者級進程在其自己私人的地址空間執行,核心將不能直接引用。
Attempts to dereference pointers passed as arguments to system calls will likely lead to problems (e.g., segmentation faults) if referenced directly.
試圖將作為直接引用的指標作為參數傳遞給系統調用並對其解引用可能會導致問題(如,段錯誤)。
Use ReadMem and WriteMem to dereference pointers passed as arguments to system calls.
使用ReadMem和WriteMem對傳遞給系統調用的指標進行解引用。