Default SWEB’s features
The following tutorial provides a short overview of the course relevant components of SWEB. The reader is required to have already a basic knowledge about key operating system concepts like threads, memory management paging, system calls, …
Whenever mentioning SWEB in this document it refers to the basic SWEB delivered to you at the beginning of the operating systems course.
The basic SWEB that is accessible for you comes with the following features:
Support for arbitrary number of threads
Paging / basic Memory management
text print to screen
A file system implementation
Feel free to implement new exciting features like a mouse driver, graphic support, network card-driver and many more, during the term
The technique of SWEB
This section explains you theoretically how SWEB is compiled, stored, booted and executed.
SWEB’s kernel is compiled by using the
g++1). The file is nothing than a default binary program. Of course there are some restrictions:
The kernel can not make use of any libaries and functions, like them provided by the libc2). The reason for that is simple. All libc calls are system calls themselves or the functions make use of system calls. Those system calls require a running operating system to handle them. Therefore when writing an operating system you have to start with nothing!
Moreover the kernel is not allowed to throw exceptions since there won’t be a runtime environment catching them.
Virtual disk-image and booting
SWEB is stored on a virtual disk image. This is a special file on the hard disk of your computer. The format of the file is equally the same as for a real hard-disk. SWEB’s image is split-up into four partitions and at it’s beginning the boot signature and a small modified version of GRUB3) are located.
The first partition contains the compiled kernel of SWEB and the second the user-programs. If you boot SWEB from the virtual machine of your choice first GRUB is invoked. Then GRUB loads the kernel into memory, and calls the boot.s from the kernel. This will setup paging and finally call a function called
startup() from the
startup() was called, SWEB is considered to be running.
Startup() will perform some setups. First determining the amount of available Kernel Memory, followed by the creation of the Kernel Memory Manager and the Page Manager. The functionality of the the most important of the mentioned components is described in detail in the following section.
Then the console is created. As you now for sure it is used to print out text to the screen. Next step the initialization of the Virtual File System.
Scheduler is created and started.
Some part of an operating system always depends on the used computer (CPU) architecture. Interrupt and execution-threads handling is platform specific to a large degree. Therefore SWEB has two separate classes called
Arch stands for “architecture) for dealing with this issue. In the following step these two classes are setup.
Now that everything necessary for managing and handling is created, the kernel-services can start to run and the user-programs can be loaded. The already created console is added to the scheduler’s list of executed threads. The second kernel thread started in the startup-sequence is the “mount-minix and start user-programs” thread. It mounts the second partition of the virtual disk-image containing the user-programs and starts them up as user-threads.
As a final step in the startup the Scheduler’s
yield() method is called, resulting in a context switch.
The course tasks relevant SWEB components / classes are explained here in short:
Operating system services are implemented as kernel threads. Examples are the console, the idle thread and the “mount-minix and start user-programs” thread (for details see above). Kernel threads have (theoretically) full access to all kernel resources. To create a kernel thread you just have to derive from the Thread base-class and implement the run method.
In basic SWEB a user program is a special kind of thread, that runs the code provided in a binary file. SWEB uses the
ELF325) format for user-programs. These programs are created by writing C code and compiling it with a compiler that is able to create
ELF32binaries, like the
GCC6) and linking SWEB’s libc to it.
Feel free to try to run your SWEB binaries on an Linux operating system and vice-versa and see what happens!
The Scheduler is the manager of the threads. Every time a timer-interrupt happens or a thread voluntary calls the Scheduler’s yield method, the Scheduler’s schedule method is invoked. It will pick the next waiting runnable thread from the list and set him as the active thread.
As you might already now, SWEB uses a very common memory management technique called paging. Therefore the memory is split-up into a number of pages with a fixed page-size (usually a power of 2). The Page Manager is the allocation unit for pages. It keeps track of used and free pages. If a thread needs another pice of memory for his code or data it has to request a page at the Page Manager.
If a CPU interrupt is triggered some code to handle it is neccessary. The implementation of platform
x86 interrupt handling can be found in the file “arch/x86/source/InterruptUtils.cpp”.
On x86 there are basically two types of interrupts. First there are errors caused while execution like divide by zero exceptions, overflows, invalid op-codes and many, many more. Second there are so called interrupt requests – short IRQ – caused by software (operating system) or by hardware (a device: keyboard, disk, network-card, …).
Let’s look briefly at the most important irq-handlers:
The timer-interrupt is caused by a timer overflow. The handler (irqHandler\_0) invokes the Schduler’s
schedule() method, which picks a new thread from the list to run.
Page Fault Handler
A page fault occurs if a thread tries to access a virtual memory location which could not be resolved to a valid physical memory address. A page fault does not automatically mean a searios error. In most cases the problem can be handled and the fault causing program can continue to run as normal. There are multiple reasons causing a page fault.
If a user-programs tries to access a memory region out of it’s range (e.g. because of a pointer error) a page fault is triggered and the program will be killed because of a protection fault. This prevents user-programs from accessing the kernel area!
Other reasons for page faults are implementation specific reasons. For instance virtual memory tries to expand the available memory by using the disk. If the memory fills up it starts to swap out (=write out) pages to the disk (swap-device) and freeing them in memory. If a page is swapped out it’s mapping is kept valid, but the present flag in the page-table entry will be cleared. If a program tries to access a swapped page it will cause a page fault. The page fault handler has to swap that page back in and the program can continue.
Another example for a page fault is explained here. A binary user-program is loaded on demand in SWEB. This means when a new user-thread running a program is created the execution code contained in the binary-file will not be loaded at all. At creation only the headers of the
ELF32 file are readout and the thread’s CPU registers – like the
EIP (=instruction pointer) – will be set. When the thread starts to run it will try to reference the memory location pointed to be instruction pointer. Since this memory location is not in memory it will cause a page fault.
This is were the Loader comes in. Each thread has an instance of a class called the Loader. The Loader manages the address space of the thread. The Loader class provides a method for loading one code page from the binary file into the memory (
Kernel Memory Manager
Handles the kernel space memory and provides a malloc/free implementation (and the overloaded-operators
delete) for kernel services. Note that this implementation is not available for user-space programs!
5) ELF32 – Executable and Linkable Format 32bit – http://en.wikipedia.org/wiki/ELF32