TDDI12: Operating Systems, Real-time and
Concurrent programming
Implementation of System Calls
The slides are based on NACHOS lectures slides of Alexandru Andrei (ESLAB) at the Linköping universitet.
Andrzej Bednarski, IDA
Linköpings universitet, 2006
• User programs in NACHOS
• User memory versus kernel memory
• File and Console relates system calls
• Synchronization of kernel functions and data structures
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.2
• Road Map through NACHOS
+ Machine: Section 2.1 – 2.4
+ Examine exception handling in machine/mipssim.cc (RaiseException) machine.cc (Machine::RaiseExcpetion) userprog/exception.cc (ExceptionHandler)
+ System calls prototypes in syscall.h
+ FileSystem and OpenFile: Section 5.2 and 5.3
+ User level prcesses: Section 4
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.3
• Source files
+ Working directory: …/code/userprog
+ Central file for assignment exception.cc: contains ExceptionHandler function syscall.h: definitions and constants for system calls
+ Files for understanding how NACHOS works progtest.cc: test routines, how to load/execute user programs main.cc: flags to NACHOS
Example of running NACHOS with a user program:
./nachos –x < user_program_name> machine/machine.{cc.h}: MIPS emulator
+ …
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.4
• Source files
+ …
+ userprog/addrspace.{cc,h}: data structures to keep track of executing user programs (address space)
+ machine/translate.cc: data structures for managing translation from virtual to physical page number
+ machine/mipssim.cc:
ReadMem, WriteMem, Translate and OneInstruction
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.5
• Programming interface to the services provided by the OS
User Application
System Calls
User Application
System Calls
User Application
System Calls
TDDI12, A. Bednarski, IDA, Linköpings universitet
System Calls
OS kernel
2.6
1
• Compiled with cross-compiler to MIPS machine code
(see …/code/test/Makefile)
+ MIPS is a RISC architecture with delayed loads
+ Cross compile: compile in one machine for a different target machine
• Emulation: runs on MIPS simulator
+ Class Machine emulates MIPS processor
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.7
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.9
• syscall machine code instruction
+ Arguments in machine registers:
Register r2 contains the system call type
Arguments to system call in register r4 - r7
System calls return values (if any) in register r2
+ See …/code/test/start.s
• ExceptionHandler
+ See …/code/userprog/exception.cc
SC_Halt: implemented
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.11
• Simple C programs
(any C program that does not use library functions)
• Source code: …/code/test
• For new test programs, add them into the Makefile
(in …/code/test)
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.8
all: halt shell matmult sort start.o: start.s ../userprog/syscall.h
$(CPP) $(CPPFLAGS) start.s > strt.s
$(AS) $(ASFLAGS) -o start.o strt.s
rm strt.s
halt.o: halt.c
$(CC) $(CFLAGS) -c halt.c
halt: halt.o start.o
$(LD) $(LDFLAGS) start.o halt.o -o halt.coff
../bin/coff2noff halt.coff halt
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.10
void Machine::Run() {
Instruction *instr = new Instruction; if(DebugIsEnabled(‘m’))
//… interrupt->setStatus(UserMode); for(;;) {
OneInstruction (instr); interrupt->OneTick();
//…
}
}
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.12
2
void Machine::OneInstruction(Instruction *instr) { int raw; int nextLoadreg = 0; int nextLoadValule = 0; if(!machine->ReadMem(registers[PCReg], 4, &raw)) return; //exception occurred instr->value = raw; instr->Decode(); pcAfter = register[NextPCReg] + 4; switch(instr->opCode) {
…
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.13
}
… switch(instr->opCode) { case OP_ADD: … case OP_DIV: … case OP_SYSCALL:
RaiseException (SyscallException, 0); return;
…
}
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.14
void Machine::RaiseException(ExceptionType which, int badVAddr) {
DEBUG(‘m’, “Exception: %s\n”, excpetionNames[which]); registers[BadVAddrReg] = badVAddr;
DelayedLoad(0, 0); //finish anything in progress interrupt->setStatus(SystemMode);
ExceptionHandler (which); //interrupts are enabled at this point interrupt->setStatus(UserMode);
}
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.15
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();
} else printf(“Unexpected user mode exception %d %d\n”, which, type);
}
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.16
• void Create(char *filename)
+ Creates an empty file
• OpenFileId Open(char *filename)
+ Opens a file for read/write
• int Read(char *buf, int size, OpenFileId id)
• void Write(char *buf, int size, OpenFileId)
• void Close(OpenFileId id)
• See …/code/userprog/syscall.h for the list of system calls
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.17
class FileSystem { public:
FileSystem(bool format) {} bool Create(char *name, int initialSize) { int fileDescriptor = OpenForWrite(name); if(fileDescriptor == -1) return FALSE; close(fileDescriptor); return TRUE;
}
OpenFile *Open(char *name) { int fileDescriptor = OpenForReadWrite(name, FALSE);
}; if(fileDescriptor == -1) return NULL; return new OpenFile(fileDescriptor);
} bool Remove(char *name) {return Unlink(name) == 0; }
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.18
3
class OpenFile { public:
OpenFile(int f) { file = f; currentOffset = 0; }
//open the file
~OpenFile() { Close(file); }
//close the file
}; int ReadAt(char *into, int numBytes, int position) { … } int WriteAt(char *from, int numBytes, int position { … } int Read(char *into, int numBytes) { … } int Write(char *from, int numBytes) { … }
…
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.19
• OpenFileId
+ Global unique id for each open file
+ ConsoleInput and ConsoleOutput
• Read and Write must choose based on the OpenFileId
+ File
+ Console
• File operation handled by FileSystem and OpenFile
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.20
• The Console class handles reading/writing form/to console at the character level
• void PutChar(char ch)
• char GetChar(void)
• see ConsoleTest
• Creating a console object
• Unique
Console(char *readFile, char *writeFile,
VoidFunctionPtr readAvail,
VoidFunctionPtr writeDone, int callArg
);
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.21
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.22
• See ConsoleTest (./nachos -c)
• void ReadAvail(int arg) { … }
• void WriteDone(int arg { … }
• console = new Console(NULL, NULL, ReadAvail, WriteDone, 0);
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.23
$600
$1000
$0000
$000
$FFF
$000
$FFF
Kernel
Process 1
Process 2
$FFFF
Physical memory
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.24
4
void UserToKernel(void) { char buffer[100]; int address = machine->ReadRegister(4); int data;
… for(int i = 0; i < filename_length; i++) { int data; machine->ReadMem(address + i, 1, &data); filename[i] = (char)data;
} filename[i] = ´\0´;
}
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.25
• File operations
+ void Create(char *filename)
Creates an empty file
+ OpenFileId Open(char *filename)
Opens a file for read/write
+ int Read(char *buf, int size, OpenFileId id)
Reads size bytes from opened file id into buf
+ int Write(char *buf, int size, OpenFileId id)
Writes size bytes to buf from opened file id
+ void Close(OpenFileId id)
Closes opened filed id
• Descriptions of system calls in:
…/code/userprog/syscall.h
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.27
• User space versus kernel space
• User address versus kernel address
• Pointers passed to system calls must be translated to/from user space
• Example:
+ Create(char *filename)
+ Read(char *buf, int size, OpenFileId id)
TDDI12, A. Bednarski, IDA, Linköpings universitet 2.26
5