If you have in depth questions, or want to explore points of confusion, or points of interest, please come to my office hours, and I'd be happy to help you.
--Tatyana Ryutov
Address Space
Address space is divided between user space in kernel space, which is done in the interest of protection.
User mode is an example of sandboxing.
Each user level process has its own sandbox, in which there is an address space. Anything outside of address space, can't be accessed by anyone else but the kernel.
The only way a user level process can access something within the kernel space is if it requests access through a syscall.
A process that spawns within kernel space, just like any other process, has its own process control block table.
A process that spawns within user space is sandboxed, but those spawning in kernel space exist in what's known as the "playground," which is not sandboxed.
A kernel level process can access memory beyond its allocated address space.
Each operating system has only one process control block table. Within this table are entries, one for every process that has spawned on the operating system. This PCB table is stored in memory. For xv6, a PCB table is structed in the form of an array, but other operating systems store it as a linked list.
Principles of operating system design
- Abstractions: simplified encapsulations of the complexities contained therein.
- Mechanisms: operations performed upon an abstraction.
- Policies: define rules governing when/how mechanisms occur
- The separation of mechanisms from the policies governing them. Policies may change, which is why it is important to have a separation between a mechanism, "how a process is performed", and a policy, "when a process is to be performed." Both may change, but they typically change at different times, and for different reasons. It makes the operating system more flexible, allowing it to accommodate new workloads, or quickly port/adapt to new technologies.
- The principle of least privilege, which requires that for a given abstraction, every module (such as a process, a user, or a program) can only access the information and resources that are necessary for it to achieve its legitimate purpose.
- The separation of implemention from interface, which allows you to change the implementation independently of the interface, making adapting to changing requirements far more flexible.
- Design for the typical, anticipate the unusual. Edge cases may occur, but design your process so that it will handle what commonly occurs in a robust, efficient way.
- Practice indirection, the management of increasing complexity through the introduction of new layers of abstraction. Indirection can be applied to solve every problem, with one exception: the reduction of excessive layers of indirection.
Do not confuse the separation of principle and interface with the separation of mechanism and policy
System Calls
- syscall
- an interface between user and OS servicees
System calls are one of the offerings an OS provides as an illusionist
Programs access system calls via high level APIs, which are wrappers around the real system call being performed.
- xv6 makes some of its system calls in C, but uses assembly to make others.
There are a few main categories of syscalls
- process control
e.g. fork() - device management
e.g. ioctl() - file management
e.g. open() - information maintenance
getpid() - communications
pipe() - protection
chmod()
A particular syscall might fall into multiple categories. For instance, read()
can be used for both device management and file management
An operating system typically has hundreds of different syscalls.
The names vary based on which operating system used. For instance, fork() in
Linux is called CreateProcess() in Windows.
Common Linux syscalls include fork(), exit(), wait(), open(), sleep(),
chmod(),
Implementation of a syscall
Note: there will be more details provided next level.
The runtime support system, typically the compiler, provides the instructions that interface with the actual system call.
- A syscall generates a trap, which invokes the kernel, who takes over, addresses the syscall, and eventually returns control back to the user.
Much like processes, files are another form of abstraction provided by the kernel.
Every syscall is associated with a particular number, stored in a table, which a
library (glibc) translates into the syscall made to the operating system. For
this reason, syscalls are an example of separation of interface from
implementation.
xv6 only has about 20 syscalls, and you'll be adding additional syscalls.
Context Switching
- the act of switching the CPU from one active process to a different process
- there are 3 steps:
- save state of current process
- load state of other process
- continue execution of that loaded process
Processor State
- The current content of the CPU registers
Kernel Organization
- Monolithic
- macOS, Linux, Windows
- it's fast because the kernel manages everything except applications, which are added in user mode.
- it's not reliable, it's not secure, just has good performance.
- Layered
- file system, virtual memory, etc., all separated from each other.
- HAL Hardware Abstraction Layer
Dynamically Installed Device Drivers
- Goal: accommodate a wide variety of physical I/O devices
Virtual Machines
Host: the underlying hardware system or OS
Hypervisor: manages the resources of the underlying hardware and provides an abstraction of one or more virtual machines
Guest: the software running within the OS
- All guest software (including the guest OS) run in user mode
Network Interface Controller NIC: a computer hardware component that connects a computer to a computer network. Early network interface controllers were commonly implemented on expansion cards that plugged into a computer bus
Containers are popular because they use fewer resources than virtual machines, the package code and dependencies are bundled together, typically run by application system kernel. A light weight standalone virtual machine. Docker is a container technology from 2012, open source, very popular. Container image becomes container at runtime. They run in the docker image, they virtualize the operating system, instead of virtualizing the hardware.
Hardware Interrupts
NMI, Non-Mask Interrupt: can't be blocked
- No other interrupts can interrupt it.
- Must complete the handler, even another NMI can't interrupt the NMI handler.
Hardware interrupts, peripheral device sends a signal through a specified pin to the processor
Have an interrupt table, stores the code for that happens during a specified interrupt.
- Stored in kernel memory
CPU Fetch-Execute Cycle
- Interrupts can happen while we are executing an instruction. We won't stop mid-instruction execution to handle an interrupt.
Hypervisors
There are two main types of hypervisors, type-1 and type-2
- Type-1, native or bare-metal hypervisors
- These hypervisors run directly on the host's hardware to control the hardware and to manage guest operating systems. For this reason, they are sometimes called bare metal hypervisors. The first hypervisors, which IBM developed in the 1960s, were native.
- Type-2 or hosted hypervisors
- These hypervisors run on a conventional operating system (OS) just as other computer programs do. A guest operating system runs as a process on the host computer. Type-2 hypervisors abstract guest operating systems from the host operating system. Parallels Desktop for Mac, QEMU, VirtualBox, VMware Player and VMware Workstation are examples of type-2 hypervisors.
Type 1 hypervisors run directly on the hardware, and for this reason are more efficient, and more secure. For this reason, they are popular in data centers, and cloud service providers.
- In this environment, syscalls made by one of the apps within one of the virtual machines within a type-1 hypervisor will go directly to the hypervisor, which sends it to the guest OS, which returns it to the hypervisor, which sends it back to the app within the VM. In total, there are 4 hops.
- Less secure, more lines of code, Linux has around 15,000,000 lines of code
Type 2 hypervisors are less efficient, but more convenient for end-users.
- When a syscall is made by one of the apps within one of the virtual machines within a type-2 hypervisor, it will go directly to the host OS, which sends it to the hypervisor, which sends it back to the host OS, which sends it to the guest OS, which sends it back to the host OS, which sends it to back to the app. In total, there are 8 hops.
- More secure, fewer lines of code, KVM has a mere 10,000 lines of code
| Performance | Reliability / Security | Flexibility | |
|---|---|---|---|
| type 1 | good | good | bad |
| type 2 | bad | bad | good |
Questions
Question 1
- student -> CPU
- program -> book
- library reading room -> memory
- librarian -> OS
- book check out record -> process control block
Question 2
We need syscalls in order to give an operating system the ability to reject a user-level process from making a harmful requests, be they unintentional/benign or intentional/malicious. A user-level process may want to access memory that it ought not be able to, or perhaps ought to, but not until later.
Question 3
When choosing a kernel organization approach, the main tradeoff OS designers face are typically between three factors
- Performance
- Security / Reliability
- Flexibility
I would choose security because computers typically become more performant as the underlying hardware gets better and better each year.
Question 4
If I had the choice between multi-boot and VM, I would choose dual-boot if I was familiar with both operating systems equally, and I didn't need to switch between one another. If either of those things weren't true, however, I'd use a virtual machine instead.
Question 5
How could we utilize hardware rings to improve protection for type 1 hypervisors?
There are four hardware rings, which we could allocate as follows:
- Hypervisor
- Guest OS software
- Device drivers
- User level applications