Suppose a process keeps running code (e.g. an infinite loop). How can other programs take over? What prevents the process from remaining active forever?
Various peripherals are connected to the main processor. When an event happens in a peripheral, the peripheral sets an electric signal which causes the processor to take some action. The act of setting this signal is called an interrupt request (IRQ for short), and the aftermath of the interrupt request on the processor is called an interrupt.
When a processor receives an interrupt, it typically does something like this:
- Mask interrupts. This means that if other IRQs happen (coming from the same peripheral or a different one), they won't be noticed just yet: they will not have any effect on the processor until interrupts are unmasked.
- Save the value of the program counter register to a register dedicated to that effect. Also save the value of a register that contains the processor mode (e.g. user mode, kernel mode, interrupt mode, …). Depending on the processor architecture, other registers may be saved as well (e.g. stack pointer).
- Switch the processor mode to interrupt mode.
- Read a value from a predefined address in memory, or from a register. This value is called the interrupt vector.
- Jump to the address given by the interrupt vector.
The code at that address is typically kernel code. On computer architectures with memory access permissions, the kernel normally prevents unprivileged processes from setting interrupt vectors or from changing the code at that address. The kernel code typically begins by copying the saved register values into memory, so that they won't be forgotten if some other interrupt occurs.
One of the peripherals that can send interrupts is the clock. To avoid a process running forever, whenever the operating system kernel allows a process to execute (by branching to its code), it first programs the clock to send an interrupt at a certain time in the future, allowing the program to run uninterrupted only for a time slice.
If the process is still running at the end of the time slice, the clock interrupt occurs. The code at the interrupt vector is kernel code, so the process is no longer running: it has been preempted. The process's code and data are still around: the kernel can later decide to let the process execute some more by restoring the saved register values (finishing with the program counter).
After the kernel has finished its basic interrupt processing, and has performed whatever tasks it deems useful, it decides which process to execute next. This decision is called scheduling.
Some operating systems (mostly on tiny embedded systems) allow processes to run as long as they like. This is known as cooperative multitasking. (And some operating systems are even more basic: they only allow a single task at a time.)
The technique is called preemptive multi tasking. See for example this Wikipedia article.
Basically the operating system runs every process for a short time, then suspends it and continues with the next process.