Operating Systems 101: Virtualisation — Direct Execution (ii)
This is a course note of an online course I took relating to the Operating System on educative.io.
Chapter 2. Direct Execution
To make a program run as fast as one might expect, OS developers came up with a technique: limited direct execution, aka. run the program directly on the CPU.
Security concerns — two modes and trap instruction
However, running operations on the CPU is not a good option all the time, as we don’t want to allow all operations directly run on the CPU. Hence the “dual mode”.
- The operating system runs in kernel mode. In kernel mode, the software has complete access to all of the computer’s hardware, and can control the switching between the CPU modes. Interrupts are also received in the kernel mode software.
- There is also the user mode. In this mode, direct access to the hardware is prohibited. For example, when running in user mode, a process can’t issue I/O requests; otherwise exception is raised.
To execute a system call, a program must execute a trap instruction. At the top of the operating system are the system calls. These are the set of abstract operations that the operating system provides to the applications programs. When a system call is initiated , the hardware transfers control to a pre-specified trap handler and simultaneously raises the privilege level to kernel mode. In kernel mode, the OS has full access to the hardware of the system. When the OS is done servicing the request, it passes control back to the user via a special return-from-trap instruction, which reverts to user mode while simultaneously passing control back to where the application left off.
Switching Between Processes
Aside from security, there is also question we need to answer about how can the OS get control of the CPU to switch processe. There are two approaches:
- A cooperative approach: wait for system calls :
In this approach, the OS trusts the processes that run for too long are assumed to periodically give up the CPU so that the OS can decide to run some other task, thus by waiting for a system call from the process or an illegal operation of some kind to take place.
- A non-cooperative approach: the OS takes control
The OS use a special timer interrupt that starts at the boot time that is programmed to raise an interrupt every so many milliseconds; when the interrupt is raised, the currently running process is halted, and a pre-configured interrupt handler in the OS runs. The OS must inform the hardware of which code to run when the timer interrupt occurs, at boot time.
Saving and restoring context during switch
The OS executes a context switch when switching the processes. A context switch is to save a few register values for the currently-executing process onto its kernel stack and restore a few for the soon-to-be-executing process.
In this example, Process A is running and then is interrupted by the timer interrupt. The hardware saves its registers to PCB0 and enters the kernel.
In the timer interrupt handler, the OS decides to switch from running Process A to Process B. At that point, it calls the
switch()routine, which carefully saves current register values to PCB0, restores the registers of Process B from PCB1, and then switches contexts, specifically by changing the stack pointer to use B’s kernel stack .
Finally, the OS returns-from-trap, which restores B’s registers and starts running it.
Worries about concurrency
Now another question, what happens when you’re handling one interrupt and another one happens?
- Disabling interrupts: OS might disable interrupts during interrupt processing; doing so ensures that when one interrupt is being handled, no other one will be delivered to the CPU.
- Locking schemes: OS also has developed a number of locking schemes to protect concurrent access to internal data structures.
That’s so much of it!