A process is an instance of a program that is being executed, or ready to be executed. Each process has its own memory (code, heap, stack, etc.), registers (think stack pointers, program counter), and other resources.
If each process has the entire memory address space to itself, how does an OS run multiple processes at the same time?
Operating systems are a protection system for processes
The OS isolates processes from each other, maintaining the illusion that each process has exclusive use of the memory and the processor.
To the programmer, we don’t have to think about how our program will fight for memory with other processes. The OS handles that.
It controls sharing data between processes (through files, the network), and it isolates itself from the process, because processes are inherently untrusted and the OS cannot let it directly interface with the trusted hardware.
Multiprocessing
A single processor can execute multiple processes “concurrently.” That’s in quotes because it actually switches between processes really, really, really, really fast. When it wants to switch to another process, the following occurs:
- It saves the current state of the registers to memory, specific for the current process.
- It schedules the next process for execution.
- It loads the saved register states for that process from memory into the actual registers, and then begins execution again.
Switching processes and address space is called context switching. This is handled by the kernel.
In a modern computer we have multiple cores in a CPU, which essentially allows multiple CPUs to execute multiple processes at once. They share the same memory. This is actual parallelism.
Creating new processes: fork()
- Creates a new child process that is almost an exact clone of the current process, called the parent
- All the memory and registers are copied from the parent
- If
fork()
is called in the middle of the program, the two processes continue execution from that point onwards e.g. the child process doesn’t start from the very beginning. They both pick up execution from wherefork()
returns. - Child process gets its own virtual address space, separate from the parent
- What’s unique about
fork()
is that its return value differs between the two processes. This is the only difference between the two processes. The parent process gets the child PID, while the child process receives 0.- Type of return value is
pid_t
, which is an integer
- Type of return value is
Process states and lifetime
A process can be in 1 of 5 states: running (currently executing), ready to run (waiting to be scheduled by the kernel), blocked, zombie, or terminated. As the OS switches between processes to execute them, a process can switch between ready and running multiple times before it’s done.
Kernel and context switching
The kernel is a shared chunk of memory-resident OS code that manages processes. It is not a separate process, but runs as part of an existing one.
How the kernel switches between processes is by taking over from the first process, context switches to the second, and then hands back control to the second process.
Assume the scheduler is nondeterministic and handled by the OS. Dun worry about it.