Terminology:
A program is the code defining an executable. It can be stored in a file, loaded into memory, downloaded from the internet.
A process is a running program. In addition to the code, it has state: the values of registers, and a virtual address space. If you run a program twice, you will create two processes (but there will only be one program).
application is a fuzzy term that I will use when I don't want to make a distinction.
Each process has its own address space; some region of memory that it controls. One possible way to manage this is by splitting memory into large chunks, and using registers to indicate the start and end of the currently running process's region. These registers are called base and limit registers.
We will also allocate a region of space for the operating system itself; this is often referred to as "kernel space".
Each process also has some state that lives in the processor: the register file (including the stack pointer, instruction pointer, etc.), and the processor flags. If we save all of the processor state, we can reload it later; from the program's perspective, nothing will have changed.
For each process, the OS maintains a process control block (PCB) (a data structure that lives in kernel space), containing the saved state of the registers, the saved virtual memory information (such as base/limit registers or a page table base register, more on this when we discuss memory).
The PCB stores all of the information the OS needs about a process. This includes (but is not limited to):
The kernel will typically organize PCBs into different queues based on their state; this way it is easy to select a new process to schedule (by looking in the ready queue), or to make runnable when input is provided (by looking at the appropriate waiting queue).
In order to make it possible for the operating system to provide isolation and access control, the processor has a special "privilege bit" that prevents certain instructions from being executed. There are many words meaning that a cpu has this bit set:
The processor will prevent certain instructions from executing when the privilege bit is cleared. For example:
The privilege bit is set in two ways:
at start-up
by a trap. All traps do two things: set the privilege bit, and jump to a handler routine defined by the operating system, (the interrupt handler, system call handler, or the exception handler as appropriate)
There are three kinds of traps:
interrupts from devices occur when the interrupt line is activated. The interrupt handler will typically invoke a driver to interact with the device.
system calls from applications occur when a syscall instruction is executed. The application will include additional information (such as a system call number) indicating what operation the application is requesting
The privilege bit is cleared by a special "return from system call" instruction, which the OS will execute when it is done processing a trap or done with initialization.
Terminology:
If you want to write an operating system, you have to write four functions: the initialization routine, the interrupt service routine, the system call handler routine, and the exception handler routine. That is the entire interface that you need to implement.
Typically, the initialization routine will:
The init process typically reads some configuration files, and forks off other processes such as the shell, servers, etc.
The system call handler routine will: - save the caller-saved registers (like a function call) - look at the arguments to the call to determine what is being requested - determine whether the request is authorized (by comparing the permissions in the running process's PCB with the operation being requested) - execute the request - either return to the requesting process, or (if the process needs to wait) saving the state to the PCB and moving it to the waiting queue
Exception and interrupt handlers are similar to system call handlers, except that the program is not expecting them, so the handler routines must save all of the processor state immediately.
Terminology:
We noted a few alternative designs for an operating system:
monolithic kernel: The kernel has a broad, high-level interface and performs many functions with the privilege bit set. For example, device drivers are linked directly into the kernel; the system call handler would jump to a disk driver, for example. A monolithic kernel has code for all of the operating system services
microkernel: The kernel has a very narrow interface, and does not communicate with devices. Drivers run in their own processes; to perform I/O processes use system calls to initiate inter-process communication (IPC) with driver processes. Driver processes have the physical addresses corresponding to memory-mapped devices mapped into their virtual address spaces. A microkernel provides only inter-process communication, memory management, and access control
virtual machine hypervisor: In a virtual machine (VM), "Processes" are themselves fully-fledged operating systems, and the hypervisor provides them a virtualized interface to the hardware. System calls are redirected to the system call handlers of the guest OS.