nachos instructional os: part 2 cs 170, tao yang, fall 2015

83
Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Upload: abigail-heath

Post on 29-Dec-2015

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos Instructional OS: Part 2

CS 170, Tao Yang, Fall 2015

Page 2: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 2

Announcement and update

Project 1 deadline was extended. Project 2 description was revised last

weekend. Start now or you miss deadline There are bonus points to submit and pass

1/3 of autograding by this Saturday. Midterm exam sample was given out. Exercise 1 will be updated in next few days. Some students still look for a partner…

Page 3: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 3

What to learn? How to execute a program in Nachos

Produce binary MIPS code from a C program Execute this MIPS code in a tiny space Make a simple Nachos system call in a C

program Project 2.

Support the execution of multiple processes Support multiprogramming and memory protection

with address translation using 1-level page table System calls for process execution. System calls for a simple file system interface.

Page 4: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

System Layers

Base Operating System (Linux for our class)

Nachos kernel threads

Thread 1 Thread 2 Thread N

Nachos OS modules(Threads mgm, File System, Code execution/memory mapping,

System calls/Interrupt)

MIPS Virtual Machine(Memory, Disk, Console)

User process:Binary code

User process:Binary code

Page 5: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Machineobject

SP

Rn

PC

memory

page table

04/19/23 5

Virtual Machine Layer

under machine subdirectory. Approximates the MIPS architecture

Can execute a sequence of MIPS instructions.

registers

Timer

Page 6: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 6

Two modes of executions User mode: execute instructions which only

access the user space. Kernel mode kernel executes when Nachos first starts up or when an instruction causes a trap

illegal instruction, page fault system call

Nachos layer

Page 7: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 7

Code execution steps in Nachos Load instructions into the machine's memory. Initialize registers (program counter, etc). Tell the machine to start executing

instructions. The machine fetches the instruction, decodes

it, and executes it. Repeat until all instructions are executed.Handle interrupt/page fault when needed

NachosNachos execution layer

MIPS Machine

User binary code

Page 8: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 8

Machine Object: Implement a MIPS machine

an instance created when Nachos starts up. Supported public variables:

Registers: 40 registers. 4KB Memory: Byte-addressable. 32 pages

(128Bytes) Virtual memory: use a single linear page

table or a software-managed TLB.

Machineobject

SP

Rn

PC

memory

page table

Page 9: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 9

Code/machine/machine.h

class Machine {char *mainMemory; // physical memory to store user program,

// code and data, while executing int registers[NumTotalRegs]; // CPU registers, for executing user

programs

TranslationEntry *pageTable;

unsigned int pageTableSize;

}

Machineobject

SP

Rn

PC

memory

page table

Page 10: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 10

Machine Object: Supported operations

Machine(bool debug);//allocate memory of 32 pages (128bytes per page). Initialize memory/register/ page table

Translate(int virtAddr, int* physAddr, int size, bool writing);

OneInstruction(); // Run one instruction of a user program.

Run(); // Run a user program ReadRegister(int num); WriteRegister(int num, int value); ReadMem(int addr, int size, int* value); WriteMem(int addr, int size, int value);

Page 11: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 11

Code/machine/ipssim.ccvoid Machine::Run(){

Instruction *instr = new Instruction; // storage for decoded instruction

interrupt->setStatus(UserMode);

for (;;) { OneInstruction(instr); //fetch and execute one instructioninterrupt->OneTick(); //advance clock

}}

Page 12: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

12

Code/machine/machine.hclass Instruction { public: void Decode(); // decode binary representation of instruction

unsigned int value; // binary representation of the instruction

unsigned char opCode; // Type of instruction

unsigned char rs, rt, rd; // Three registers from instruction.

int extra; // offset or other purpose. Treat as 0};

Page 13: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

13

Code/machine/ipssim.ccVoid Machine::OneInstruction(Instruction *instr) {

//Fetch an instruction and then decodeif (!machine->ReadMem(registers[PCReg], 4, &raw)) return; //if error, returninstr->value = raw; instr->Decode();// Execute the instruction switch (instr->opCode) {

…case OP_ADDU: registers[instr->rd] = registers[instr->rs] + registers[instr->rt];break;case OP_SW: machine->WriteMem(registers[instr->rs], 4, registers[instr->rt]); break;…case OP_SYSCALL: RaiseException(SyscallException, 0); return;…

}// Advance program counters.registers[PCReg] = registers[NextPCReg]; registers[NextPCReg] = pcAfter; //which is registers[NextPCReg] + 4;}

Page 14: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

14

Code/machine/translate.ccbool Machine::WriteMem(int addr, int size, int value) { ExceptionType exception; int physicalAddress;

exception = Translate(addr, &physicalAddress, size, TRUE);//address translation if (exception != NoException) { machine->RaiseException(exception, addr); return FALSE; }

switch (size) { //Copy value to the target physical memory address properlycase 1: machine->mainMemory[physicalAddress] = (unsigned char)

(value & 0xff); break; case 2: *(unsigned short *) &machine-

>mainMemory[physicalAddress] = ShortToMachine((unsigned short) (value & 0xffff)); break;

case 4:….

}}bool Machine::ReadMem(int addr, int size, int *value) {…}

Page 15: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

A Simple Page Table

PFN 0PFN 1

PFN i

page #i offset

user virtual address

PFN i+

offset

process page table

physical memorypage frames

Each process has its own page table. Virtual addresses are

translated relative to the current page table.

Page 16: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

ExceptionType Machine::Translate(int virtAddr, * physAddr, size, writing) {unsigned int vpn, offset; TranslationEntry *entry; unsigned int pageFrame;

// calculate virtual page number, and offset within the page vpn = (unsigned) virtAddr / PageSize; offset = (unsigned) virtAddr % PageSize;

entry = &pageTable[vpn];pageFrame = entry->physicalPage;

entry->use = TRUE; // set the use, dirty bits if (writing) entry->dirty = TRUE;

*physAddr = pageFrame * PageSize + offset; // compute physical address return NoException; } 16

Code/machine/translate.cc

Physical page use bit | dirty bit

Page 17: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Machineobject

SP

Rn

PC

memory

page table

04/19/23 17

Virtual Machine Layer

registers

Timer

Interrupt

Page 18: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 18

Interrupt Object Maintain an event queue with a simulated clock. Supported operations:

Schedule(VoidFunctionPtr handler, int arg, int when, IntType type) Schedule a future event to take place at time ``when''.

Usage: schedule a yield at random interval. SetLevel(IntStatus level). Used to temporarily disable and re-

enable interrupts. Two levels are supported: IntOn and IntOff. OneTick()—advance 1 clock tick CheckIfDue(bool advanceClock). Examines if some event

should be serviced. Idle(). ``advances'' to the clock to the time of the next

scheduled event

Page 19: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 19

Interrupt::OneTick()

Software managed clock. The clock advances 1 tick after one binary

instruction execution with user mode , 10 with system mode

after every restored interrupt (disable/enable Interrupt)

or after the MIPS simulator executes one instruction.

When the ready list is empty, fast-advance ticks until the next scheduled event happens.

Page 20: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

20

Timer object Generate interrupts at regular or random intervals Then Nachos invokes the predefined clock event

handling procedure. Supported operation:

Timer(VoidFunctionPtr timerHandler, int callArg, bool doRandom).

Create a real-time clock that interrupts every TimerTicks (100) time units Or set this a random number for random mode

nachos –rs 0Setup a random timer that requests a thread yield

Page 21: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

21

Console Object Simulates a character-oriented CRT device Data can be written to the device one character at a time

through the PutChar() routine. Input characters arrive one-at-a-time. They can be retrieved

by GetChar(). Supported operations:

Console(char *readFile, char *writeFile, VoidFunctionPtr readAvail,VoidFunctionPtr writeDone, int callArg).

Create a console instance.``readFile'' is the Unix file of where the data is to be read from; if NULL, standard input is assumed.

PutChar(char ch) GetChar()

Page 22: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 22

Disk Object

Simulates the behavior of a real disk. The disk has only a single platter, with multiple tracks

(32). Each track contains the same number of sectors (32). Allow only one pending operation at a time. Contain a ``track buffer'' cache. Immediately after

seeking to a new track, the disk starts reading sectors, placing them in the track buffer.

Supported operations: Disk(char *name, VoidFunctionPtr callWhenDone, int

callArg) ReadRequest(int sectorNumber, char *data) WriteRequest(int sectorNumber, char *data) ComputeLatency(int newSector, bool writing)

Page 23: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Executing a user program

data

user spaceMIPS instructions executed

by the emulator

Nachos

kernelMIPS emulator

halt

Machineobject

fetch/executeexamine/deposit

SaveState/RestoreStateexamine/deposit

Machine::Run()

ExceptionHandler()

SP

Rn

PC

registers memory

page table

process page tables

Page 24: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

From C program to MIPS binary

int j;char* s = “hello\n”;

int p() { j = write(1, s, 6); return(j);}

myprogram.c

gcccompiler

…..p: store this store that push jsr _write ret etc.

myprogram.s

assembler data

myprogram.o

linker

object file

data program

(executable file)myprogram

datadatadata

libraries and

other objects

Page 25: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 25

Binary code format (Noff)Source code: under userprog subdirectory. Current Nachos can run a single MIPS binary (Noff

format) type ``nachos -x ../test/halt''.

A user program must be compiled using a cross-platform gcc compiler that generates MIPS code.

A Noff-format file contains (bin/noff.h) the Noff header, describes the contents of the rest of

the file executable code segment (TEXT) initialized data segment (DATA) uninitialized data segment (BSS).

Page 26: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Space usage during execution of a C program

Stack grows from top-down.

Heap grows bottom-up

Uninitialized data

STACK

HEAP

BSS

DATA

TEXT

Initialized data

Code

Page 27: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 27

TEXT, DATA, BSS, HEAP, STACK in C

Int f3=3; /* DATA segment */Int f1; /*BSS segment*/def[] = "1"; int main(void)

{static char abc[12]; /* BSS segment */ static float pi = 3.14159; int i = 3; /* Stack*/char *cp; cp= malloc(10); /* HEAP for allocated chunk*/f1= i+f3; /* code is in TEXT. f1 on STACK*/

strcpy(abc , "Test" );

}

DATA or BSS?

DATA or BSS or STACK?

DATA or BSS or STACK?

Where is “Test”? DATA or BSS or STACK?

STACK

HEAP

BSS

DATA

TEXT

Page 28: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 28

TEXT, DATA, BSS, HEAP, STACK in C

Int f3=3; /* DATA segment */Int f1; /*BSS segment*/def[] = "1"; /* DATA segment */int main(void)

{static char abc[12], /* BSS segment */static float pi = 3.14159; /* DATA segment */int i = 3; /* Stack*/char *cp; /*stack*/cp= malloc(10); /*malloc allocates space from HEAP*/f1= i+f3; /* code is in TEXT*/

strcpy(abc , "Test" ); /* “Test” is located in DATA segment */

}

STACK

HEAP

BSS

DATA

TEXT

Page 29: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 29

Noff format. Each segment has the following

information: virtualAddr: virtual address that segment begins at. inFileAddr: Pointer within the Noff file

where that section actually begins. The size (in bytes) of that segment.

STACK

HEAP

BSS

DATA

TEXT

Page 30: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23

size = noffH.code.size + noffH.initData.size +

noffH.uninitData.size+ UserStackSize

User process for executing a program

A Nachos thread is extended as a process Each process has its own address space containing

Executable code (Code segment) Initialized data (Data segment) Uninitialized data (BSS) Stack space for function calls/local variables

how big is address space?

A process owns some other objects, such as open file descriptors.

Page 31: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 31

Steps in User process creationCurrently only execute a single user program.1. Create an address space.2. Zero out all of physical memory (machine-

>mainMemory)3. Read the binary into physical memory and initialize

data segment.4. Initialize the translation tables to do a one-to-one

mapping between virtual and physical addresses.5. Zero all registers, setting PCReg and NextPCReg to 0

and 4 respectively.6. Set the stackpointer to the largest virtual address of

the process (stack grows downward).

Page 32: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 32

Key Calling graph when Nachos executes under userprog directory

main() inmain.cc

Initialize()in system.cc

StartProcess ()in progtest.cc

Space=New AddrSpace()in addrspace.cc

Space->InitRegisters()

Executable fileReadAt()

Space->RestoreState()

Machine->Run ()in mipssim.cc

Machine->WriteRegister()

Machine->OneInstruction()

Interupt->OneTick()In Interupt.cc

Page 33: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

void StartProcess(char *filename) { OpenFile *executable; AddrSpace *space;

executable = fileSystem->Open(filename); if (executable == NULL) { printf("Unable to open file %s\n", filename); return; } space = new AddrSpace(executable); currentThread->space = space; delete executable; // close file space->InitRegisters(); space->RestoreState(); machine->Run(); ASSERT(FALSE);}

Creating a Nachos Process (code/userprog/progtest.cc)

Create an AddrSpace object, allocating physicalmemory and setting up the process page table.

Set address space of current thread/process.

Initialize registers, load pagetable, and begin execution in user mode.

Create a handle for reading text and initial data out of the executable file.

Run binary code

Page 34: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

AddrSpace::AddrSpace(OpenFile *executable) { NoffHeader noffH; unsigned int i, size; executable->ReadAt((char *)&noffH, sizeof(noffH), 0);

// how big is address space? size = noffH.code.size + noffH.initData.size + noffH.uninitData.size + UserStackSize; // we need to increase the size to leave room for the stack numPages = divRoundUp(size, PageSize); size = numPages * PageSize;

pageTable = new TranslationEntry[numPages]; for (i = 0; i < numPages; i++) { pageTable[i].virtualPage = i; // for now, virtual page # = phys page # pageTable[i].physicalPage = i; pageTable[i].valid = TRUE; } ....

Creating a Nachos Address Space (code/userprog/addrspace.cc)

Read the header of binary file

Compute address space need

Setup a page table for address translation

Page 35: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

bzero(machine->mainMemory, size);

// copy in the code and dataif (noffH.code.size > 0) { executable->ReadAt(&(machine->mainMemory[noffH.code.virtualAddr]), noffH.code.size, noffH.code.inFileAddr); }

if (noffH.initData.size > 0) { executable->ReadAt(&(machine-

>mainMemory[noffH.initData.virtualAddr]), noffH.initData.size, noffH.initData.inFileAddr); }

Initializing a Nachos Address Space

Zero out memory allocated

Copy code segment to memory

Copy initialized data segment to memory

Page 36: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

36

Compilation of halt.c Test/halt.c:

#include "syscall.h"main() { Halt(); /* not reached */}

…Halt: addiu $2,$0,SC_Halt syscall j $31.end Halt

main:….jal Halt

gcc -S

start.s has system call entries.System call number is always in register 2

halt.s: assembly code of halt.c

Test/start.s

Page 37: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 37

Nachos –x halt using halt.c in test directory

Interrupt->Halt()In Interupt.cc

Machine->RaiseException(SyscallException)

Machine->Run ()in mipssim.cc

ExceptionHandler(SyscallException)

Machine->OneInstruction()

Page 38: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

38

Code/userprog/exception.ccExceptionType Machine::Translate(int virtAddr, *

physAddr, size, writing) {

void ExceptionHandler(ExceptionType which) { int type = machine->ReadRegister(2);

if ((which == SyscallException) && (type == SC_Halt)) {

DEBUG('a', "Shutdown, initiated by user program.\n");

interrupt->Halt(); } }

// Code Convention: // system call code -- r2 // arg1 -- r4, arg2 -- r5, arg3 -- r6, arg4 -- r7

Page 39: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 39

Summary: actions of “nachos –x halt”

1. The main thread starts by running function StartProcess() in file progtest.cc. This thread is used to run halt binary.

2. StartProcess() allocates a new address space and loads the halt binary. It also initializes registers and sets up the page table.

3. Call Machine::Run() to execute the halt binary using the MIPS emulator.1. The halt binary invokes the system call Halt(), which causes a

trap back to the Nachos kernel via functions RaiseException() and ExceptionHandler().

4. The exception handler determines that a Halt() system call was requested from user mode, and it halts Nachos.

Page 40: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 40

Assignment 2: Multiprogramming&System Calls

Modify source code under userprog subdirectory. ~500-600 lines of code.

The crossplatform compiler is under ~cs170/gcc/. This compiler on x86 machines produces a.out with the

coff format. Use utility coff2noff (under nachos’ bin directory) to

convert it as Noff. Check the makefile under test subdirectory on how to use

gcc and coff2noff. System calls to be implemented:

Multiprogramming: Fork(), Yield(), Exit(), Exec() and Join(). File and console I/O: Creat(), Open(), Read(), Write(), and

Close().

Page 41: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Multi-Processes and the Kernel

text

data

BSS

user stack

0

data

2n-1

Nachos kernel0

2n-1

text

data

BSS

user stack

0

data

text

data

BSS

user stack

0

data

Fork or Execbinary

Page 42: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 42

To run multiple processes

Nachos should Provide the physical memory management;

Fill memory with proper data, instruction. Set up an address translation table with

linear page tables; Save/restore address-space related state

during process switching (AddrSpace::SaveUserState() and AddrSpace:RestoreUserState() are called).

Page 43: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

43

Project 2: Files involved Key files. (Red for modification/extension)

progtest.cc -- test routines to run user code. addrspace.h addrspace.cc -- create an address space and load the program from

disk. syscall.h -- the system call interface. exception.cc -- the handler for system calls and other user-level exceptions such

as page faults. filesys.h, openfile.h console.h -- interface to the Nachos file system and console

(connected Linux file system) Extension : pcb.cc, memorymanager.cc processmanager.cc, openfilemanager.cc,

useropenfile.cc Other related files:

bitmap.h bitmap.cc -- manipulate bitmsps (useful for keeping track of physical page frames).

translate.h, translate.cc -- translation tables. machine.h, machine.cc -- emulates main memory, processor, etc. mipsim.cc -- emulates MPIS R2/3000 instructions. console.cc -- emulates a terminal using UNIX files.

Page 44: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

44

Project 2: Makefile flow make -C userprog

userprog subdirectory. You expand here Produce nachos which supports processes and system

calls make -C bin

bin subdirectory. No change is needed Produce programs that read Nachos binary code format

used by test program compilation make -C test

test subdiretory. Add your test cases here Produce MIPS binary code for test cases. Executed as ../userprog/nachos –x binaryname

Page 45: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

45

Deadline Earlier submission of partial

results for 2 bonus points May 3 Pass 1/3 of autograding tests

Full submission May 12 (35 points)

Page 46: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Project 2: Implementation Notes

Tao Yang

Page 47: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Part I: Multiprogramming

void Fork(func) creates a new user-level (child) process, whose address space starts out as an exact copy of that of the caller (the parent),

void Yield(): temporarily relinquish the CPU to another process.

void Exit( status) call takes a single argument, which is an integer status value as in Unix. The currently executing process is terminated.

SpaceID Exec(filename) spawns a new user-level thread (process), but creates a new address space. It should return to the parent a SpaceId.

int Join(ID) call waits and returns only after a process with the specified space ID has finished. Return the exit code collected.

Page 48: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Getting Started Review syscall.h (under userprog directory). Review start.cc (under test directory) which includes all system

call stubs, following the style of Halt. Modify ExceptionHandler() in exception.cc to include all system

call entries. After each system call, increment PC registers so that

ExceptionHandler() execution flow returns back to next instruction after user’s system call place.

counter = machine->ReadRegister(PCReg); machine->WriteRegister(PrevPCReg,counter); counter = counter + 4; machine->WriteRegister(PCReg,counter); counter = counter + 4; machine->WriteRegister(NextPCReg,counter);

Arguments of a system call are in Registers 4, 5, 6 etc. how to verify? You may review MPIS assembly code

produced for a test C program using gcc with -S. If needed, return result is register 2

machine->WriteRegister(2,result);

Page 49: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Process Control Block (PCB)

Information associated with each process Process state Program counter CPU registers CPU scheduling information Memory-management information

Page table Accounting information I/O status information

Page 50: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

PCB (Process Control Block) Write the PCB and a process manager. Create a PCB

class that will store the necessary information about a process. To start, it should have a PID, parent PID, and kernel

ThreadID. pcb.h, pcb.cc

The process manager- getPID and clearPID methods, which return an unused process id and clear a process id. Maintain state, exit status, conditional waiting processmanager.h, processmanager.cc.

Page 51: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Diagram of Process State

Page 52: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Memory Manager Write a Memory Manager that will be used to

facilitate memory allocation: Track memory page usage. Allocate a page Free a page memorymanager.cc/memorymanager.h

Modify AddrSpace:AddrSpace (addrspace.cc) to use the memory manager. Modify the page table constructors to use pages

allocated by your memory manager Create a PCB (process control block) also for each

process to include key control information.

Page 53: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Management of Free Pages

Before allocation After allocation

Can use vector of bits to represent availability of each page00110001110001101 … 110010 1allocated, 0free

Page 54: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

AddSpace.cc Write a function (e.g. AddrSpace::Translate),

which converts a virtual address to a physical address. It does so by breaking the virtual address into a page table index and an offset. Already in the harness code release

Write a function( e.g. AddrSpace::ReadFile), which loads the code and data segments into the translated memory, instead of at position 0. Read data into a system buffer (diskBuffer). Copy buffered data into proper memory locations

(e.g. at machine->mainMemory[physAddr].)

Page 55: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Address Translation for Paging

Logical address = logical page number + page offsetRole of page table: logical page number physical page numberPhysical address = physical page number + page offset

Page 56: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

How to Run User Processes Concurrently?

2n-1

text

data

BSS

user stack

0

datatext

data

BSS

user stack

0

data

text

data

BSS

user stack

0

data

0

2n-1

…Machine->run()…

…Machine->run()…

…Machine->run()…

Nachos Kernel Threads

Main program Forked process Forked process

binary

Create a Nachos kernel thread to manage each user process and execute its binary!

Page 57: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos system call Fork() Fork() creates a new process with a duplicated

space from parent, but executes a specific function.

Not same definition as syscall.h Difference compared to Linux fork()?

Func1(){ char *str = “Hello\n"; Write(str, 6, 1);}main(){ char *str = "Greetings from the parent!\n"; Fork(Func1); Write(str, 28, 1);} Hello

Greetings from the parent!

Page 58: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

58

Compilation of a Fork program#include "syscall.h“Func1(){}

main() { Fork(Func1);

Fork(Func1);}

Func1:…

main:...la $4, Func1jal Fork

… la $4, Func1

jal Fork…

gcc -S

Assembly code

…Fork: addiu $2,$0,SC_Fork syscall j $31.end Fork…

System call number is in register 2.Argument 1 is in register 4

Test/start.s

Page 59: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23 59

Questions on Forking a Process When to spawn a new kernel thread?

Do we directly use thread fork function to execute the binary of a child? Thread->Fork(Func1, NULL)? Thread->Fork(Machine->Run, NULL)?

Who needs to set the program counter for the new process? Parent thread vs child thread?

Machine->RaiseException(SyscallException)

Machine->Run ()in mipssim.cc

ExceptionHandler(SyscallException)

Machine->OneInstruction()

Page 60: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

User Process and Nachos Kernel Threads

2n-1

0

2n-1

text

data

BSS

user stack

0

data

…Machine->run()…

ForkBridge {…Machine->run()…}

ForkBridge {…Machine->run()…}

Nachos Kernel Threads

Main programtext

data

BSS

user stack

0

datatext

data

BSS

user stack

0

data

Forked process Forked process

Thread fork

binary

Spawn a thread which executes ForkBridge(). ForkBridge() manages each user process.

Page 61: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement Fork() in ExceptionHandler()

1. Func1 address is in register 4.Target function to be executed in the new space.

2. Create a new kernel thread.3. Create a new AddrSpace to be a duplicate

of the CurrentThread's space and get a new PCB.

4. The new thread runs a dummy function that creates a bridge for execution of the user function).

1. Call NewThread->Fork(ForkBridge, Func1)5. The current thread calls Yield() so the

new thread can run.

Page 62: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

ForkBridge() : Key parts

Set counter = Func1 Initialize and restore the registers. For

example, currentThread->RestoreUserState(); currentThread->space->RestoreState(); machine->WriteRegister(PCReg, counter); machine-

>WriteRegister(PrevPCReg,counter-4); machine-

>WriteRegister(NextPCReg,counter+4); Call machine->Run() which executes the

forked user process starting from the desired Func1 address.

Page 63: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos system call Exec() Exec() creates a new process with new code

and data segments from a file. Return the new address space ID.

Only use the first argument. Difference compared to Linux exec()?

main(){ char *str = "Greetings from the parent!\n"; Write(str, 28, 1); Exec("../test/hello“, 0,0,0); Write(str, 28, 1);}

Greetings from the parent!Greetings from the parent!

Page 64: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement Exec()main(){ char *str = "Greetings from the parent!\n"; Write(str, 28, 1); Exec("../test/hello“, 0,0,0);}

2n-1

0

2n-1

text

data

BSS

user stack

0

data

…Machine->run()…

Nachos Kernel Threads

Main programtext

data

BSS

user stack

0

data

new process

ExecLauncher {…Machine->run()…}

Thread fork

binary

Page 65: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement Exec() Exec handler creates a new process from a file.

Allocate a new address space which fits this file. Load data/code from an OpenFile object constructed from

the filename passed in by the user. In order to get that file name you will have to write a

function that copies over the string from user space. Allocate a new kernel thread and a PCB to execute

with the above space. Fork the new thread to run a dummy bridge function

that sets the machine registers straight and runs the code Call NewThread->Fork(execLauncher ,NULL);

The calling thread should yield to give control to the newly spawned thread.

Return the space ID.

Page 66: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Bridge function for Exec()

Called execLanucher() in the released harness code.

Initialize registers/restore state. (currentThread->space)->InitRegisters(); (currentThread->space)->RestoreState();

Machine->run();

Page 67: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos system call Yield() Current process gives up CPU and yields to

another process

Func1(){ char *str = “Hello\n"; Yield(); Write(str, 6, 1);}main(){ char *str = "Greetings from the parent!\n"; Fork(Func1); Write(str, 28, 1); }

Greetings from the parent!Hello

Page 68: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

CPU Switch From Process to Process

Page 69: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement Yield(): Context Switch

Save the current user process state. AddrSpace:SaveState()

Current process state is READY. Conduct the current kernel thread switch with thread

yield. When returns, restore the user process restate

AddrSpace:RestoreState()Yield()

0

…Machine->run()…

Nachos Kernel Threads

Process A Process B

Bridge{…Machine->run()…}

Thread yield

0

Two context switches involved1.Process context switch

Who saves/restores state?2.Kernel context switch Who saves/restores state?

Page 70: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

04/19/23

Key operations of Nachos’ function Thread::Yield()

SWITCH ()in switch.s

nextThread = scheduler->FindNextToRun(); if (nextThread != NULL) { scheduler->ReadyToRun(this); scheduler->Run(nextThread); }

Restore currentcontext.

Save current context

SWITCH()

Thread:Yield()

Page 71: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos threads/scheduler:Run()

#ifdef USER_PROGRAM if (currentThread->space != NULL) { currentThread->SaveUserState(); currentThread->space->SaveState(); }#endifSWITCH(oldThread, nextThread);…#ifdef USER_PROGRAM if (currentThread->space != NULL) { currentThread->RestoreUserState(); currentThread->space->RestoreState(); }#endif

Page 72: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos system call int Join(SpaceId id)

Wait until the completion of a specific process and return exit code.

int main() { int i, c, ret; for( i=0 ; i <1 ; ++i ) { c= Exec( “hello“,0,0,0 ); ret=Join(c);}

0

2n-1

…Machine->run()…

Nachos Kernel Threads

Main program new process

ExecLauncher {…Machine->run()…}

Thread fork

c=Exec()Join(c)

0

Exit(0)

0

Page 73: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement Join() If the child process already finishes, return its exit

status Who maintains such info?

Change the current process state as blocked Call ProcessManagerfor a conditional waiting. When waking up,the current process state should beRunning. Return the exit code of child process.

Join()

0

…Machine->run()…

Nachos Kernel Threads

Process A Process B

Bridge{…Machine->run()…}

Thread yield

0

ProcessManager/PCB

Page 74: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos system call Exit (int code)

Exit the current process and return the exit code

int main() { int i, c, ret; for( i=0 ; i <1 ; ++i ) { c= Exec( “hello“,0,0,0); ret=Join(c);}

0

2n-1

…Machine->run()…

Nachos Kernel Threads

Main program new process

ExecLauncher {…Machine->run()…}

Thread fork

c=Exec()Join(c)

0

Exit(0)

0

Page 75: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement Exit() Exit code is in register 4 Set the exit status of this process in PCB Release resource allocated to this process

Close files opened. Change the current process state as Terminated Broadcast everybodythat I exit. Clear/release the address space of this process. Clear/release the currentkernel thread

threadFinish()

Join()

0

…Machine->run()…

Nachos Kernel Threads

Process A Process B

Bridge{…Machine->run()…}

Thread yield

Exit(0)

0

ProcessManager

Page 76: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Review of Linux System Calls for Files

fileHandle = open(pathName, flags) fileHandle = creat(path,  flags);

errorCode = close(fileHandle) byteCount = read(fileHandle, buf, count)

byteCount = write(fileHandle, buf, count) position=lseek(fileHandle, offset, flag)Re-position the offset of the current file location

for next read/write.

Current offset

countNew offset

Page 77: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

What is the output content of tmpfile?

tmpfile

Child Parent

main() { int pid, fd; char *s1;

fd = open("tmpfile", O_WRONLY | O_TRUNC | O_CREAT, 0666);

pid = fork(); if (pid > 0) { sleep(1); /* Delay the parent by 1 second */ s1 = "Parent\n"; } else { s1 = "Child\n"; } write(fd, s1, strlen(s1)); close(fd);}

Create if it does not exist.

Remove content if exist

Page 78: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

What is the output content of tmpfile?

tmpfile

Parentt

Child

main() { int pid, fd; char *s1;

pid = fork();

fd = open("tmpfile", O_WRONLY |O_CREAT, 0666);

if (pid > 0) { sleep(1); /* Delay the parent by 1 second */ s1 = "Parentt"; } else { s1 = "Child"; } write(fd, s1, strlen(s1)); close(fd);}

Page 79: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Nachos system calls for files void Create(char *name);

OpenFileId Open(char *name);

void Write(char *buffer, int size, OpenFileId id);

int Read(char *buffer, int size, OpenFileId id);

void Close(OpenFileId id);

New offsetCurrent offset

count

Page 80: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

System Calls for File System

For the entire system, maintain a set of objects (SysOpenFile class) representing system-wide opened files. Each file may be opened by many user processes. Each file has filename, and offset for the current

read/write pointer Do parent/child processes share the same offset pointer?

For create/Open/Read/Write, Nachos already has a simple file system implemented Use FILESYS_STUB compiler directive Directly use

Linux interface filesys.cc and openfile.cc under filesys directory

Page 81: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement open() 0, 1, 2 file descriptors are reserved for Linux

stdin, stdout, stderr. Make sure parent/child processes share files

opened before Fork(). Offset is shared. Use fileSystem->Open() (nachos’open) to locate

the file object. Add the opened file object to the system-wide

fileOpenTable. Keep track files opened for each process.

Close them during Exit() as not all of them are closed.

Page 82: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement read() Allocate an internal buffer. If Inputfile ID is ConsoleInput

Then use getchar() and save data in the internal buffer.

Read until EOF or \n. Else, find the current read offset.

Use openFile:ReadAt (defined in openfile.h) to read data (essentially use Linux read())

Copy data from the internal buffer to the destination memory location. Need to copy one byte by one byte since the

address needs to be translated one by one.

How to deal the file offset shared between parent/child processes?How to deal with the file offset not shared?

Page 83: Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Implement write()

Allocate an internal buffer. Copy data from the source memory

location to the internal buffer. Need to copy one by one since the address

needs to be translated one by one. If Outputfile ID is ConsoleOutput

Then use console output (essentially, printf assuming string type).

Else, find the current write offset. Use openFile:WriteAt (defined in openfile.h)

to write data to the Linux file.

How to deal the file offset shared between parent/child processes?How to deal with the file offset not shared?