Software layering

Most software wants to run on a variety of platforms; this requires them to be "platform-agnostic", to varying degrees. Conversely, low-level system software is generally designed to be "general-use", meaning that it provides important features common to all expected higher-level software.

Together, this means that a program designed to check e-mail shouldn't care about the protocol the mainboard speaks to your hard-disk, or how many processors you have, but rather that this should be provided by lower levels of software.

Read The Anatomy of an Operating System from The Linux Sea to learn about the layers of software.

One of the ways the separation of concerns is maintained is by concealing details. On modern computer systems, programs are run with virtualised memory addressing: the kernel presents a fictional view of memory to user programs, omitting the kernel's private memory, so that user programs do not grow too attached. Read the Wikipedia article on virtual address spaces.

Unikernel systems

General computing systems are designed to be able to run a large variety of software (such as the systems described above). Many computing systems today are not "general" in this sense: the hardware may be perfectly capable of running a variety of software, but the system has been assembled with the goal of running a very limited set of software.

Examples of such devices are microwaves, 2000s-era televisions, 1990s-era automobiles, most scientific calculators, computing systems used in control systems (e.g. for aerospace, automobiles, industrial), and some of the less-intelligent "smart" systems (e.g. lightbulbs).

The most extreme cases of these "integrated" or "embedded" situations remove the separation of kernel and user-space: a highly specialised kernel is compiled together with the desired user program, and all features unused by the program are removed from the kernel. These systems are called unikernels; read the Wikipedia article on unikernel systems.

Virtual machines

In the other direction, sometimes even more layers are required. Many large tech companies now provide "cloud computing" facilities: essentially computers-for-rent. Renters are given network access to a blank operating system, or sometimes even a blank machine (no operating system!). These machines are not physical, though: they are simulations of the physical machine, allowing many customers to share a single physical computer.

The physical computers run software emulating CPUs, memory, network cards, etc., and these emulations run their own kernel with its own virtualised hard-disk and operating system. That operating system has its own userspace (chosen by the renter), running on top of the virtualised kernel, which itself runs on top of a user program (the emulator, chosen by the rental company), on top of a kernel on a physical computer.

Even more complications can be introduced, either as security precautions, or for the convenience of either renter or cloud provider.

Read the Wikipedia articles on virtual machine and cloud computing.

Combinatorial explosion

Depth of layering should be viewed as a spectrum; a designer must choose a point on this spectrum.

Even further out than cloud computers, the operating system Qubes approaches a virtual machine for each running program, to prevent different programs from attempting to attack each other.

Intermediate is the situation with popular mobile phone operating systems: applications are "sandboxed", wherein they are allowed to access some underlying system resources, but not others. (E.g. library sharing is essentially limited to libraries chosen by the operating system developer.)

Also popular is lifting "dangerous" or "unreliable" software to higher layers: microkernels are the opposite of unikernels. In a microkernel, the kernel contains the bare minimum for resource management and inter-process communication (IPC); hardware management and many other tasks are moved into small user-space programs. Because of this, a fault in the e.g. graphics driver may result not in kernel crash (requiring a hard reboot of the machine), but just restarting a background program running the driver.