Operating System
An operating system (OS) is system software that manages a computer's hardware resources and provides a common environment and set of services in which applicat...
| Classification | System Software |
|---|---|
| Purpose | Managing computer resources and providing an environment for program execution |
| Managed Resources | Central Processing Unit, Memory, Secondary Storage, Input/Output Device, network resources |
| Core Components | Kernel, System Call, File System, Device Driver, system services |
| Main Functions | Process Management, Memory Management, input/output management, file management, security and access control |
| Execution Environment | An abstraction layer between user programs and hardware |
| Main Types | Batch Operating System, Time-Sharing Operating System, Real-Time Operating System, Distributed Operating System, Embedded Operating System |
| Main Families | Unix-like, Windows Family, mainframe operating systems, mobile operating systems |
| Related Fields | Computer Architecture, Concurrency, Virtualization, Computer Security, Distributed System |
An operating system (OS) is system software that manages a computer's hardware resources and provides a common environment and set of services in which application programs can run. It allocates resources such as Central Processing Unit execution time, memory, storage devices, input/output devices, files, and network connections among multiple programs. It also provides abstract interfaces that allow applications to read files, create processes, and use displays, networks, and peripheral devices without directly controlling the specific operations of the hardware. The kernel, the central component of an operating system, runs with elevated privileges and is responsible for process and thread scheduling, virtual memory, device drivers, input/output, and protection mechanisms. Applications generally request kernel functions through system calls and system libraries. Another major role of an operating system is to reduce the impact that a program error or unauthorized access can have on other programs and on the operating system as a whole by running applications in a restricted user mode and assigning each process a separate address space and access permissions.
An operating system is not limited to the kernel alone. An actual operating environment is formed by combining the kernel with device drivers, system libraries, background services, an initialization system, user account and security mechanisms, a command-line shell or graphical user interface, and administrative tools. However, the boundary between the operating system and the kernel is defined differently depending on the system and context. Some architectures separate kernel functions into independent servers running in user space, while others integrate many functions directly into the kernel. Operating systems are implemented not only as general-purpose systems for personal computers and servers, but also as specialized or real-time systems for smartphones, game consoles, network equipment, automobiles, industrial controllers, and small embedded devices. They use different architectures and policies according to requirements such as response time, safety, power consumption, memory capacity, and user interface design.
History
Early electronic computers did not have operating systems in the modern sense. Computers were supplied as hardware together with basic operating instructions, and programmers had to load programs directly into the machine and configure the execution environment themselves. Programs and data were recorded on punched cards, paper tape, magnetic tape, and other media. When one job finished, a human operator had to reconfigure the equipment before the next job could run. During this period, it was difficult for another user to access the system while the computer was executing a program, and preparing programs and switching equipment required a considerable amount of time.
The history of operating systems began with attempts to use computer resources more efficiently and automate complex hardware operations through software. Early control programs merely managed the loading and execution order of jobs, but they later developed into complex systems that simultaneously managed the Central Processing Unit, memory, storage devices, input/output devices, users, and programs.
Early Computers and Manual Operation
In computers of the 1940s and early 1950s, it was common to execute only one program at a time. Users reserved a period of computer time and entered programs and data directly into the machine. When an execution error occurred, they had to modify the program and prepare it again from the beginning.
Early computers were extremely expensive, but the Central Processing Unit often remained unused while programs were being prepared or equipment was being changed. Even while a program waited for a slow input/output device such as a card reader or printer, no other job could run. This led to the development of resident monitors and control programs that allowed the computer itself to manage job execution order and device operations.
GM-NAA I/O, developed in the mid-1950s, is often mentioned as a pioneering example of an early operating system. It was developed for the IBM 704 by user groups at General Motors and North American Aviation and provided functions for automatically executing jobs in sequence and standardizing input/output processing. The Computer History Museum's operating-system preservation materials describe the GM-NAA family of systems as one of the starting points in the development of early mainframe operating systems.
Batch Processing
Batch Processing is a method in which multiple programs and their data are prepared as a collection of jobs and then entered into a computer by an operator for automatic sequential execution. Users did not receive results immediately after submitting a job and instead had to wait until the system had processed all preceding jobs before receiving the output.
Batch systems reduced the time required for humans to reconfigure equipment for every job. They used job control languages and resident monitors to automate program loading, execution, error handling, and output processing. Early operating systems were responsible for managing the Central Processing Unit and input/output devices while executing these batch jobs sequentially.
However, simple batch processing still left the Central Processing Unit idle whenever the running program waited for input/output. To reduce this idle time, input/output operations were processed through separate devices and channels, and Multiprogramming was developed to load multiple programs into memory so that another program could run while one was waiting.
The Computer History Museum describes early batch processing as a non-interactive method in which users submitted jobs and waited for the results, and explains that time-sharing later transformed computer use into an interactive process.
Multiprogramming
Multiprogramming is a method in which multiple programs are loaded into memory and the Central Processing Unit is assigned to another program whenever one program is waiting for input/output. This made it possible to use the Central Processing Unit and input/output devices concurrently and increase the overall throughput of the system.
To implement multiprogramming, an operating system had to provide functions such as the following:
- Placing multiple jobs in memory
- Protecting memory between programs
- Scheduling to select the next job to execute
- Handling interrupts that signal the completion of input/output
- Managing files and device states for each job
- Preventing errors from spreading to other jobs
Through this process, operating systems developed from simple job-execution tools into resource allocators and protection managers. Core concepts of modern operating systems, including CPU scheduling, memory management, interrupts, device drivers, and file systems, began to take shape during this period.
Time-Sharing Systems
A Time-Sharing System divides Central Processing Unit execution time into short intervals and assigns them alternately to programs belonging to multiple users. Each user interacts with the computer through a terminal, and because the system rapidly switches between users, each person receives an experience similar to using the computer exclusively.
Unlike batch processing, in which users submitted programs and received results much later, time-sharing allowed them to enter commands, immediately inspect the results, and modify their programs interactively. The Computer History Museum explains that time-sharing developed in the early 1960s as a way for multiple users to share expensive mainframe resources and overcome the inconvenience of batch processing.
The Compatible Time-Sharing System (CTSS), developed at MIT, was one of the most important early time-sharing systems. CTSS development began in 1961, and by around 1963 it was operating reliably on a large scale, demonstrating the practical feasibility of time-sharing. Users could edit and execute programs through remote terminals and use files and user accounts.
Time-sharing systems required more than general CPU sharing. They also needed user authentication, file protection, interactive shells, process isolation, and accounting for resource usage. These requirements contributed to the formation of the structure of modern multi-user operating systems.
Multics
Based on experience with CTSS, MIT, General Electric, and Bell Labs began developing Multics in the mid-1960s. Multics aimed to provide a computer utility through which multiple users could reliably access computing resources in a manner similar to public services such as electricity or telephone networks. Development plans became more concrete beginning in 1964, and the system's design goals were publicly presented at an academic conference in 1965.
Multics introduced features that were highly advanced for its time:
- A hierarchical file system
- A storage structure integrating files and virtual memory
- Dynamic linking
- Fine-grained access permissions
- Protection rings
- Multiprocessor support
- Online system reconfiguration
- Operating-system implementation using a high-level language
- Continuous time-sharing service for multiple users
Although Multics encountered difficulties because of its complexity and development delays, it had a long-term influence on operating-system security, file systems, virtual memory, dynamic linking, and system architecture. Multics began in 1965, was used commercially, and its final operational system was shut down in 2000.
IBM System/360 and OS/360
In 1964, IBM announced the IBM System/360 family, which was designed so that computers with different performance levels and prices could share a compatible instruction set and software. Previously, computer families intended for different purposes and sizes often used different instruction sets and software, but System/360 attempted to apply a single compatible architecture across multiple models.
OS/360, developed for System/360, was a large-scale project intended to support systems of various sizes and both commercial and scientific computing workloads through a single family of operating systems. OS/360 provided batch processing, multiprogramming, peripheral-device management, and a common software environment.
The development of OS/360 became far more complex and difficult than expected and became an important case in the history of software engineering. Supporting an enormous set of features and multiple hardware configurations at the same time created difficulties in scheduling and quality management, encouraging broader discussion about the organization and design methods of large software projects.
The compatibility strategy of System/360 and OS/360 established a direction in which users could continue using existing software and data even after upgrading to a higher-performance computer. This influenced the later adoption of backward compatibility as an important value in operating systems and hardware platforms.
Emergence of Virtual Machines
During the 1960s, IBM researched virtualization technology that allowed a single physical computer to be used as multiple independent virtual computers. CP-40 and CP-67 developed an architecture in which multiple virtual machines could be created on the System/360 family, with a separate operating environment running inside each virtual machine.
IBM's CP/CMS research began with CP-40 in 1964, developed into CP-67, and was officially introduced as VM/370 in 1972. Each user could use an independent virtual machine and interactive environment, and the system could be used for operating-system development, testing, and user isolation.
Virtual machines continued to be used for many years in mainframe environments and re-emerged as a core technology during the 2000s as server consolidation and cloud computing became widespread.
Birth of UNIX
After Bell Labs withdrew from the Multics project, Ken Thompson, Dennis Ritchie, and others began developing a smaller and simpler operating system. The first version of UNIX was developed on a PDP-7 computer around 1969 and was later ported to the PDP-11.
UNIX was initially written in assembly language, but it was later rewritten in C (Programming Language), which was developed by Dennis Ritchie. Implementing a substantial part of the operating system in a high-level language made it easier to port to other hardware, and C and UNIX spread together.
A 1974 paper by Ritchie and Thompson described the UNIX file system, processes, and command interface. UNIX provided a hierarchical file system, process creation, pipes, the abstraction of devices as files, and a command environment in which small programs could be combined.
The main design characteristics of UNIX included the following:
- A simple, file-centered interface
- Separation of process creation from program execution
- Connecting small tools through pipes
- Text-based configuration and data processing
- Multi-user and time-sharing support
- High portability through C
- A relatively clear distinction between the operating system and user tools
The first UNIX Programmer's Manual was written in 1971. During the 1970s, UNIX was distributed to universities and research institutions together with its source code, leading to the development of many variations.
BSD and Commercial UNIX
At the University of California, Berkeley, BSD was developed based on UNIX. BSD advanced technologies such as virtual memory, job control, the Fast File System, TCP/IP networking implementations, and the socket API. BSD networking technology influenced the Internet and many operating systems.
At the same time, AT&T UNIX and various commercial UNIX systems such as SunOS, HP-UX, and AIX appeared. Although each system supported different hardware and features, an increasing number of incompatible extensions and tools divided the UNIX ecosystem into multiple branches.
Standardization efforts such as POSIX and the Single UNIX Specification were pursued to reduce these differences. These standards defined common interfaces for processes, files, shells, and system APIs, with the goal of increasing source-code portability among UNIX-family systems.
Real-Time Operating Systems
While general mainframe and time-sharing operating systems developed around throughput and user responsiveness, Real-Time Operating Systems were developed for industrial control and military and aerospace systems in which tasks had to be completed within defined time limits.
For a real-time operating system, predictable response time even under worst-case conditions is more important than being fast on average. Features such as priority-based scheduling, fast interrupt handling, restricted memory allocation, and prevention of priority inversion became important considerations.
Real-time operating systems later came to be widely used in factory automation, automobiles, aircraft, communication equipment, medical devices, robots, and small embedded devices.
Personal Computer Operating Systems
With the appearance of microprocessors and personal computers in the 1970s, operating systems expanded from multi-user environments on large mainframes to small computers used by individuals.
CP/M, developed by Gary Kildall, was a representative commercially successful operating system for early microcomputers. CP/M was developed around 1974 and provided a common environment in which the same applications could be used on 8-bit computers made by different manufacturers. The Computer History Museum describes CP/M as the first commercially successful personal computer operating system.
CP/M separated hardware-specific input/output operations into the BIOS, making it relatively easy to port the operating system to other computers. CP/M 1.3, released in 1976, included a BIOS architecture that made machine-specific input/output code easier to modify. This structure helped computers from different manufacturers share a common software ecosystem.
After the IBM PC appeared in 1981, PC DOS and MS-DOS, supplied by Microsoft, spread rapidly. MS-DOS was initially a relatively simple command-line operating system centered on a single user and a single task, but it became the de facto standard environment as IBM PC-compatible computers grew in popularity. The IBM PC used an Intel 8088 processor and Microsoft's DOS and greatly accelerated the adoption of personal computers in businesses and homes.
Graphical User Interfaces
Early personal computer operating systems mainly used command-line interfaces, but graphical user interfaces based on windows, icons, menus, and pointers became widespread through research at Xerox PARC in the 1970s and commercial products in the 1980s.
The Apple Lisa and Macintosh were early commercial computers that provided graphical interfaces and mouse input to ordinary users. The Macintosh popularized an environment in which files and programs were manipulated through icons and windows.
Microsoft announced Windows in 1983 as a graphical operating environment running on top of MS-DOS, and the first product was released in 1985. Early versions of Windows depended on DOS, but the platform later transitioned to an independent operating-system architecture centered on the Windows NT family.
The spread of graphical interfaces expanded the role of operating systems. Operating systems came to manage not only processes and files but also windows, graphics, fonts, printing, multimedia, input devices, accessibility, and consistent application interfaces.
Network Operating Systems
As personal computers and workstations became connected through networks, operating systems began providing remote file and printer sharing, user authentication, electronic mail, remote login, and distributed resource-access functions.
UNIX and BSD became major foundations for Internet servers and workstations through their broad support for TCP/IP. Novell NetWare and the Windows Server family provided file, printing, and account services within enterprises, while multiple operating systems became interconnected around network protocols and directory services.
As networking changed from an optional operating-system capability into a basic function, security models also changed. Previously, the main focus had been on separating users and processes within the same computer. Later, remote attacks, network authentication, encryption, firewalls, and automatic security updates became core operating-system functions.
Microkernel Research
During the 1980s, the Microkernel architecture, which separates operating-system functions into a small kernel and user-space servers, became an active area of research. A microkernel attempted to retain only minimal functions for address spaces, threads, and inter-process communication inside the kernel while running services such as file systems, device drivers, and networking in separate processes.
Mach, MINIX, and QNX are representative examples. The microkernel architecture offered advantages in service isolation, replacement, and system modularity, but the cost of inter-process communication and context switching could create performance problems.
Microkernel concepts were later incorporated into many operating systems not only in pure form but also through mixed and hybrid kernel architectures. Windows NT and Apple's XNU developed as architectures combining elements of traditional monolithic kernels and microkernels.
Linux and Open Development
In 1991, Linus Torvalds developed and publicly released a new kernel for computers based on the Intel 80386. The Linux 0.01 release documentation explains that the kernel used features of the 386 processor and was developed in an environment similar to MINIX.
Linux was combined with the compiler, shell, libraries, and tools of the GNU Project to form a complete UNIX-family operating environment. As its source code was made public and many developers participated through the Internet, it became a representative example of a distributed open-development model.
Linux began as an experimental kernel for personal 386 computers but was later ported to multiple CPU architectures and to servers, supercomputers, network equipment, embedded devices, and smartphones. Linux development has continued since 1991 through public mailing lists and version-control systems.
The development of Linux changed the previous assumption that an operating system had to be developed entirely within a single company. An ecosystem emerged in which multiple companies, individuals, and research institutions jointly contributed to one kernel while each organization created different distributions and products.
Windows NT
Separately from the MS-DOS family, Microsoft developed Windows NT with security, portability, multi-user support, and preemptive multitasking in mind. Windows NT 3.1 was released in 1993 and later became the foundation of Windows 2000, Windows XP, and the modern Windows family.
Windows NT provided a separation between user mode and kernel mode, virtual memory, security identifiers and access control lists, a hardware abstraction layer, and an architecture supporting multiple execution environments. Consumer versions of Windows were later unified around the NT family, bringing the DOS-based Windows line to an end.
Windows was used not only on personal computers but also on enterprise servers, workstations, gaming systems, and various industrial devices. It developed around its graphical user interface, backward compatibility, and extensive hardware and application ecosystem.
NeXTSTEP and macOS
In the late 1980s, NeXT developed NeXTSTEP, combining a UNIX-family foundation, an object-oriented development environment, and the Display PostScript graphics system. NeXTSTEP was based on Mach and BSD technologies and later became the foundation of Apple's next-generation Mac operating system after Apple acquired NeXT.
Apple developed Mac OS X using technology from the NeXTSTEP family to replace the existing Classic Mac OS. Mac OS X provided the XNU kernel, which combined a Mach-based kernel with a BSD user environment, as well as new graphics and application frameworks. Its name was later changed to OS X and then to macOS.
The operating-system technology of this family expanded beyond macOS to become a shared foundation for iOS, iPadOS, watchOS, tvOS, and visionOS. Apple's modern operating systems provide user interfaces designed for different devices while sharing kernel, security, development tools, and various system technologies.
Mobile Operating Systems
As mobile phones developed from voice-centered devices into general-purpose computers, mobile operating systems became a separate and important field. Palm OS, Symbian, Windows Mobile, and BlackBerry OS were used in early smartphones and personal digital assistants.
In 2007, Apple introduced the iPhone, and its operating system later developed under the name iOS. iOS applied the kernel and security architecture of a desktop operating-system family to a mobile environment and was designed around touch interfaces, power management, sensors, mobile communication, application distribution, and permission control.
Android, led by Google, combined the Linux kernel with a framework and application execution environment for mobile devices. As Android was adopted by multiple manufacturers, semiconductor companies, and mobile carriers, it spread across a wide variety of smartphones, tablets, televisions, automobiles, and embedded devices.
Mobile operating systems tended to apply application isolation, code signing, permission requests, centralized application distribution, power saving, and restrictions on background execution more strongly than desktop operating systems. These security and distribution models later influenced desktop operating systems as well.
Popularization of Virtualization
Virtualization had existed since the mainframe era, but it spread widely again in the late 1990s and 2000s for x86 servers. Software-based virtualization, followed by hardware virtualization support in CPUs, made it possible to run multiple operating systems simultaneously on a single physical server.
Virtualization brought changes such as the following:
- Server consolidation
- Isolation of operating systems and applications
- Cloning and migration of virtual machines
- Automation of development and testing environments
- Disaster recovery and snapshots
- Resource partitioning for cloud computing
As a virtual machine monitor, or hypervisor, allocated hardware resources among multiple guest operating systems, the operating system became established as a layer capable of running not only on physical hardware but also on virtual hardware.
Containers and Operating-System-Level Virtualization
Unlike virtual machines, each of which runs a separate kernel, Containers share a single operating-system kernel while isolating processes, file systems, networks, users, and resource usage.
Modern container environments developed through technologies such as UNIX chroot, BSD jail, Solaris Zones, and the combination of Linux namespaces and cgroups. Docker simplified the user experience of creating and distributing container images, while Kubernetes provided a foundation for deploying and managing containers across multiple servers.
With the spread of containers, the role of the operating system expanded beyond managing a single physical computer toward supporting numerous isolated application environments, resource limits, network namespaces, and image execution.
Cloud Computing and Large-Scale Data Centers
In cloud computing, the operating system became a foundation for combining physical servers, virtual machines, containers, networks, and storage. Linux and Windows Server are used in large-scale data centers and are integrated with hypervisors, container runtimes, and orchestration systems.
Cloud environments strengthened requirements for operating systems such as the following:
- Support for large-scale multicore systems
- Virtualization performance
- Network and storage throughput
- Automatable management interfaces
- Observability and remote diagnostics
- Real-time security updates
- Resource isolation and usage measurement
- Automatic recovery from failures
The boundary between operating systems and distributed systems also became increasingly blurred. While the operating system of a single server manages local resources, cluster-management systems allocate CPU, memory, and storage across multiple servers as though they were a single resource pool.
Security-Centered Development
The security of early operating systems primarily focused on separating the files and processes of multiple users. As computers became connected to the Internet and began processing personal information, financial data, and industrial infrastructure, the scope of operating-system security expanded greatly.
Modern operating systems have developed security features such as the following:
- Separation of user mode and kernel mode
- Virtual address spaces
- Access control lists
- Permission-based and role-based access control
- Execution prevention and address space layout randomization
- Code signing and secure boot
- Sandboxing
- Application permissions
- Disk and file encryption
- Integrity checking
- Automatic security updates
- Hardware security modules and trusted execution environments
Because security vulnerabilities can become connected to privileges across the entire operating system, research has continued into reducing the size of kernel code and device drivers, improving memory safety, and minimizing the attack surface.
Modern Operating Systems
Modern operating systems are the result of combining many historical lineages and designs. Mainframe operating systems continue to process large-scale transactions and enterprise data, while concepts from UNIX and BSD continue through Linux, macOS, and various server and mobile operating systems. The Windows NT family broadly supports personal computers and enterprise environments, while Linux is used as the foundation of servers, cloud systems, supercomputers, embedded devices, and Android devices.
Today, operating systems are used in different forms in environments such as the following:
- Personal computers
- Smartphones and tablets
- Servers and cloud systems
- Mainframes
- Supercomputers
- Game consoles
- Automobiles and robots
- Network equipment
- Smart appliances
- Industrial controllers
- Sensors and microcontrollers
- Virtual machines and containers
The history of operating systems is not simply a process in which new products replaced older ones. Job management developed in early batch systems, multi-user and interactive execution from time-sharing systems, protection and virtual memory from Multics, the simple interfaces and portability of UNIX, graphical user environments from personal computers, virtualization from mainframes, and sandboxing and power management from mobile systems all remain present together in modern operating systems.
Operating systems have continuously changed alongside advances in hardware. As the performance of the Central Processing Unit, memory, and storage devices improved, operating systems provided more abstractions and protection mechanisms. As computers became deeply connected to networks and everyday life, security, isolation, power management, and automatic updates became increasingly important. Operating-system structures and roles will continue to evolve in response to new hardware architectures, virtualization, distributed computing, security requirements, and real-time demands.
Architecture
An operating system is a collection of components that manage resources and provide a common execution environment between hardware and application programs. At the center of an operating system is the Kernel, around which system libraries, background services, file systems, device drivers, command-line shells, graphical user interfaces, and administrative tools are combined. The specific composition of an operating system and the privilege level at which each component runs vary according to its design.
Modern general-purpose operating systems generally divide the execution environment into User Mode and Kernel Mode. Applications run in user mode with restricted privileges, while the kernel and major device drivers run in kernel mode, where they can access hardware and the entire memory space. In Windows, applications also run in user mode, while core operating-system components run in kernel mode, although some drivers can also run in user mode. [1]
Application Programs
↓
System Libraries and Runtimes
↓
System Call Interface
↓
Kernel
├── Process and Thread Management
├── CPU Scheduling
├── Memory Management
├── File Systems
├── Networking
├── Security and Access Control
└── Device Drivers
↓
Computer Hardware
The separation between user mode and kernel mode prevents applications from arbitrarily modifying physical memory or directly controlling hardware devices. When an application needs to open a file, allocate memory, create a process, or send network data, it must request the operation from the kernel through an interface provided by the operating system. The kernel verifies the validity of the request and the caller's access permissions before performing the required operation.
Not every operating-system function necessarily runs inside the kernel. Functions such as file indexing, network configuration, login management, printing, and graphical-session management may be handled by system services running in user space. Some operating systems also run certain device drivers and parts of file systems in user space to reduce the effect that a fault can have on the entire kernel.
Operating-System Components
An operating system generally consists of the following components:
- The kernel manages processors, memory, interrupts, and hardware resources.
- The system call interface provides a path through which user programs request kernel functions.
- The process and thread management system creates and terminates execution units and allocates CPU time.
- The memory management system manages physical memory and virtual address spaces.
- The file system organizes files, directories, and data on storage devices and manages access permissions.
- The input/output system buffers and schedules device requests and delivers their completion results.
- Device drivers translate general operating-system input/output requests into device-specific commands.
- The network stack manages network interfaces, communication protocols, and sockets.
- The security system controls user and process privileges, authentication, and access to resources.
- System services provide operational functions outside the kernel, including login handling, network configuration, and device discovery.
- The user interface allows users to operate the system through a command-line or graphical environment.
The boundaries between these components differ among operating systems. Windows kernel mode includes not only the kernel responsible for low-level scheduling and interrupt handling, but also the Executive layer, which manages objects, memory, processes and threads, input/output, and configuration. [2]
In Apple's XNU-based operating systems, Mach, BSD, I/O Kit, file systems, and networking components together form the kernel environment. Therefore, the term kernel in this context refers not only to the Mach core itself, but to the combination of multiple kernel components. [3]
Types of Kernel Architecture
Operating systems can be classified into several architectures according to how their functions are distributed between the kernel and user space. In practice, operating systems often combine characteristics of multiple approaches rather than following one architecture in a pure form.
Monolithic Kernel
A Monolithic Kernel runs process management, memory management, file systems, networking, and many device drivers within a single kernel address space.
Because the components operate with the same privileges and can directly call functions within the same address space, communication overhead between them is relatively low. However, a memory error in a single driver or kernel component can affect other components and the entire operating system.
Linux is generally classified as a monolithic kernel, but it also provides a modular architecture that allows kernel modules to be added or removed while the system is running. Kernel modules allow drivers and features to be loaded as needed instead of including all of them in the default kernel image.
Microkernel
A Microkernel retains only minimal functions such as scheduling, address-space management, interrupt handling, and inter-process communication inside the kernel, while separating services such as file systems, networking, and device drivers into user-space processes.
Because services run in separate address spaces, the failure of one service can have a reduced effect on the kernel and other services. This design also makes it easier to replace or restart services and separate their privileges. However, calling services requires inter-process messaging and address-space transitions, which can introduce additional overhead depending on the design and implementation.
MINIX 3 and QNX are commonly classified as representative microkernel-based systems.
Hybrid Kernel
A Hybrid Kernel uses some aspects of a microkernel's layered architecture while running multiple operating-system services in kernel space for performance or compatibility.
The Windows NT family and Apple's XNU are commonly classified as hybrid kernels. XNU combines Mach functionality, BSD components, I/O Kit, file systems, and networking functions within a single kernel environment. [4]
The term hybrid does not refer to one strictly defined implementation. The decision of which functions run in the kernel and which remain in user space differs among operating systems.
Modular Kernel
A Modular Kernel separates the kernel's core functions from additional features and provides functions such as device drivers and file systems as modules that can be loaded while the system is running.
Modules can be loaded into memory only when needed, allowing support for new hardware or file systems to be added without rebuilding the entire kernel. However, kernel-mode modules generally run with the same privileges as the kernel, so a faulty module can affect the entire system.
Exokernel
An Exokernel is an experimental architecture in which the kernel handles only the protection and allocation of hardware resources, while high-level abstractions such as file systems and networking are delegated to applications or library operating systems.
Applications can select resource-management methods suited to their own purposes, but separate libraries and execution systems are required to provide a common environment for general applications. Exokernels are significant primarily in research on operating-system abstractions and resource management rather than as a mainstream architecture for commercial general-purpose operating systems.
Kernel
The Kernel is the operating-system component that runs with the highest privileges and manages the system's core resources. It controls processor execution modes, memory, interrupts, processes and threads, input/output devices, and access permissions.
Windows documentation explains that the kernel provides low-level fundamental operations such as thread scheduling and hardware interrupt delivery and serves as a central function on which other parts of the operating system depend. [5]
The kernel's primary roles include the following:
- Creating and terminating processes and threads
- Selecting which runnable thread receives CPU time
- Configuring the virtual address space of each process
- Managing physical memory and page replacement
- Handling hardware interrupts and exceptions
- Managing kernel objects such as files, sockets, and devices
- Checking user and process access permissions
- Providing inter-process communication and synchronization
- Running file systems and the network stack
- Providing a common input/output foundation for device drivers
During the boot process, the kernel initializes memory management, interrupts, processors, and devices before starting the first user-space process. Afterward, most application code runs in user mode, and control moves to the kernel only when required through mechanisms such as system calls and interrupts.
Errors inside the kernel have a greater impact than ordinary application errors. Because the kernel can access the entire address space and all devices, invalid pointers, synchronization errors, and driver faults can lead to system crashes, data corruption, and security vulnerabilities. Kernel code therefore requires a restricted execution environment, strict synchronization, and careful input validation.
System Calls
A System Call is an official entry point through which a user-space program requests a function provided by the kernel. The Linux manual defines system calls as entry points into the Linux kernel and explains that applications generally invoke them through wrapper functions in libraries such as the C standard library rather than executing them directly. [6]
Representative system calls provide functions such as the following:
- Opening and closing files
- Reading and writing data
- Creating processes and threads
- Replacing a program image
- Mapping virtual memory
- Creating sockets and performing network communication
- Retrieving time and system information
- Inter-process communication
- Changing permissions and user information
- Sending device-specific control requests
A typical system-call flow is as follows:
Application Program
↓
System Library Function
↓
Prepare System Call Number and Arguments
↓
Enter Kernel Mode Through a Special Instruction
↓
Kernel System Call Handler
↓
Validate Permissions and Arguments
↓
Execute Kernel Subsystem
↓
Return Result or Error
↓
Return to User Mode
Each system call has a number or internal identifier that distinguishes it, and arguments are passed through CPU registers or memory. The exact calling convention differs according to the CPU architecture and operating-system ABI. The Linux syscall() function can execute the corresponding kernel call using a system call number and arguments, but ordinary programs use the library function associated with each system call. [7]
System calls and ordinary function calls serve different purposes. An ordinary function call may execute within the same privilege level and address space, while a system call crosses the protection boundary between user space and kernel space. This process requires an execution-mode transition, argument validation, and verification of access to user memory.
Apple's kernel documentation also describes BSD system calls, ioctl, Mach messages, and memory mapping as methods of crossing the boundary between user space and the kernel. Crossing this boundary introduces not only performance costs but also security concerns because data supplied from user space must be validated. [8]
System calls form the stable user-space interface of an operating system. For existing applications to continue running even when the internal kernel implementation changes, the ABI—including system call numbers, arguments, return values, and error-handling rules—must remain compatible.
File Systems
A File System is a system that organizes data from storage devices, memory, networks, and other sources into files and directories and manages information such as names, locations, sizes, owners, access permissions, and timestamps.
Applications generally do not directly specify the physical sector locations of storage devices. Instead, they use paths and file names to open files and read or write data at logical positions within those files. The operating system and file system translate these requests into storage-device blocks and input/output commands.
The main functions of a file system include the following:
- Creating and deleting files and directories
- Resolving file names and paths
- Reading and writing file data
- Managing file sizes and locations
- Managing access permissions for users and groups
- Allocating and reclaiming storage space
- Managing file and directory metadata
- Connecting and mounting storage devices
- Managing caches and buffers
- Recovering the file system after failures
- Handling symbolic links and hard links
- Supporting memory mapping and file locking
An operating system can provide multiple types of file systems through a common interface. Linux's Virtual File System provides a file-system interface to user programs and forms an abstraction layer that allows different file-system implementations to coexist within the kernel. System calls such as open, read, write, and stat pass through the VFS before reaching the actual file-system implementation. [9]
Application Program
↓
System Calls Such as open / read / write
↓
Virtual File System
↓
Actual File System
├── ext4
├── XFS
├── Btrfs
├── FAT
├── NTFS
├── APFS
└── Network File System
↓
Block Device Driver
↓
Storage Device
The virtual file-system layer represents files, directories, mount points, and open files as common objects. Actual file systems implement operations conforming to the common interface, allowing disk-based, memory-based, and network file systems to be used through the same file API.
File systems are not limited to permanent storage devices. An operating system may also provide temporary file systems that exist only in memory and virtual file systems that expose process and device information as files. In UNIX-family operating systems, devices, pipes, and some sockets can also be accessed through the file-descriptor interface.
File systems use different policies to balance performance and data reliability. Caching write data in memory instead of immediately committing it to a device can improve performance, but data that has not yet been written may be lost if power is interrupted. Technologies such as journaling, write-order control, and copy-on-write are used to improve file-system consistency and recoverability after an abnormal shutdown.
Device Drivers
A Device Driver is software responsible for communication between an operating system and a specific hardware device. It translates general input/output requests used by the operating system into register accesses, commands, and memory transfers understood by the device and reports device interrupts and completion states back to the operating system.
Devices managed by drivers include the following:
- Storage devices
- Keyboards and mice
- Graphics processing units
- Network interfaces
- Audio devices
- USB devices
- Cameras and sensors
- Printers
- Virtual devices
- System buses and power-management devices
A typical device input/output flow is as follows:
Application Program
↓
File, Socket, or Graphics API
↓
System Call
↓
Operating-System Input/Output Manager
↓
Device Driver
↓
Device Controller and Hardware
↓
Interrupt or Completion Signal
↓
Device Driver
↓
Deliver Result to the Requesting Process
A driver may handle device initialization and shutdown, input/output request queues, interrupt processing, direct memory access, power management, error recovery, and device connection and removal.
An operating system may provide a common driver interface for each category of device. For example, a storage-device driver implements common operations required by the file system and block input/output layer, while a network driver implements a common interface for exchanging packets with the network stack. This removes the need for higher-level operating-system components to understand every hardware detail of each device.
Windows kernel-mode drivers can use Executive services that include object, memory, process and thread, input/output, and configuration-management functions. Windows connects devices and drivers hierarchically and passes input/output requests through driver stacks. [10]
Drivers do not necessarily have to run in kernel mode. User-mode drivers run with restricted privileges, reducing the possibility that a fault will halt the entire operating system. Windows allows some device drivers to run in user mode, while Apple provides DriverKit for writing user-space device drivers on macOS and iPadOS. [11] [12]
However, devices that require interrupts and extremely low latency, devices needed during the early boot process, and devices directly connected to internal kernel functions may still require kernel-mode drivers.
Because device drivers run close to the kernel and hardware, they have a major effect on operating-system stability and security. Invalid memory access and synchronization errors in a kernel-mode driver can halt the entire system. Operating systems therefore strengthen driver trust boundaries through methods such as driver signing, privilege restrictions, user-mode drivers, and input/output memory management units.
Relationships Between Components
The kernel, system calls, file systems, and device drivers are not independent functions. They operate in sequence to process a single request.
The process of reading data from a file may proceed as follows:
1. The application calls the read function.
2. The system library executes a system call.
3. The CPU switches from user mode to kernel mode.
4. The kernel checks the file descriptor and access permissions.
5. The virtual file system locates the open file and its actual file system.
6. The actual file system calculates the blocks in which the data is stored.
7. If the data is not present in the cache, a block input/output request is created.
8. The storage-device driver translates the request into a device command.
9. The device transfers the data and generates a completion interrupt.
10. The kernel completes the request and returns the data to the application.
11. The CPU returns to user mode.
In Linux, read() is a system call that reads data from the file represented by an open file descriptor and returns the result of the actual transfer to the caller. [13]
In this way, an operating-system architecture is a layered system that connects multiple subsystems through protection boundaries and common interfaces. System calls form the boundary between user programs and the kernel, file systems provide data through the common abstraction of files, and device drivers translate the operating system's logical requests into actual hardware operations.
Although internal layers and terminology differ among operating systems, they share the fundamental purpose of abstracting complex hardware through common interfaces and allowing multiple programs to share resources safely.
Execution and Resource Management
Rather than giving running programs direct control over resources such as the Central Processing Unit and memory, an operating system provides abstractions such as Processes, Threads, and Virtual Memory. Each program behaves as though it exclusively controls the processor and memory, but the operating system actually distributes and protects limited physical resources among multiple execution units. Through this virtualization of resources, the operating system can run multiple programs concurrently and limit the effect that an error or excessive resource usage in one program has on other programs and the system as a whole. In operating-system theory, CPU and memory virtualization are also treated as core areas alongside concurrency and persistent storage.
A program file consists of static code and data stored on a storage device, whereas a process represents the dynamic state of that program while it is actually running. The operating system creates a process by loading the program into memory and configuring information such as its execution context, address space, open files, and access permissions. Multiple processes can be created from a single program file, and each process generally has an execution state and resources distinct from those of other processes.
Program
↓ Execution
Process
├── Virtual Address Space
├── One or More Threads
├── Open Files and Input/Output State
├── User and Access Permissions
├── Signal and Exception State
└── Various Resources Managed by the Operating System
Processes and Threads
A Process is the basic isolation unit used by an operating system to manage a running program and its resources. A process may include not only the code to be executed, but also global data, a heap, stacks, memory mappings, open files, a current working directory, user privileges, and references to various kernel objects.
The operating system maintains an identifier and state information for each process. The specific internal data structures used to represent processes differ among operating systems, but they generally need to contain information such as the following:
- Process identifier
- Parent and child process relationships
- Process execution state
- Virtual address-space information
- Associated threads
- Open files and input/output resources
- User and security credentials
- CPU time and memory usage
- Signal and exception-handling state
- Scheduling and resource-limit information
A process contains one or more Threads. A thread actually executes instructions within a process and is the unit to which the operating-system scheduler allocates CPU execution time. Threads belonging to the same process generally share code, global data, the heap, open files, and the virtual address space, but each thread has its own execution context, stack, and register state. Windows also defines a thread as an execution unit that can be scheduled within a process and explains that threads in the same process share its virtual address space and system resources.
Process
├── Shared Code
├── Shared Global Data
├── Shared Heap
├── Shared Open Files
├── Shared Virtual Address Space
│
├── Thread 1
│ ├── Instruction Position
│ ├── CPU Registers
│ └── Stack
│
├── Thread 2
│ ├── Instruction Position
│ ├── CPU Registers
│ └── Stack
│
└── Thread 3
├── Instruction Position
├── CPU Registers
└── Stack
Using multiple threads within one process allows several tasks to proceed concurrently while sharing the same data and resources. A program can separate a thread that handles the user interface from one that reads files and another that processes network requests. On a multicore processor, multiple threads may also execute in parallel.
Because threads share more resources than processes, creating and switching between threads can generally require less overhead than creating new processes. However, because threads can access shared memory concurrently, Race Conditions, data corruption, and Deadlocks may occur. Mechanisms used to control these problems, including Mutexes, Semaphores, condition variables, and atomic operations, are discussed in ## Concurrency and Communication.
The way an operating system implements threads is not fixed to a single model. A user-space runtime may map multiple user threads onto a smaller number of kernel execution units, or each user thread may correspond to one kernel thread. NPTL, the common modern POSIX thread implementation on Linux, maps each thread one-to-one to an execution unit that can be scheduled by the kernel and uses Linux's clone family of facilities for thread creation.
The exact boundary between processes and threads can also differ among operating systems. Some kernels manage processes and threads as completely separate objects, while others configure a common type of execution-unit structure differently depending on how resources such as address spaces and files are shared. Therefore, the description of a process as a unit of resources and protection and a thread as a unit of execution and scheduling should be understood as a general conceptual distinction.
Process Creation and Termination
A new process is created at the request of an existing process or as part of system initialization. When creating a process, the operating system prepares a new identifier, address space, initial thread, security information, and kernel-management structures.
UNIX-family operating systems traditionally combine fork, which duplicates an existing process, with the exec family of functions, which replaces the program executed by the current process.
Existing Process
↓ fork
Parent Process + Child Process
↓ exec
Execute New Program
When fork is called, the child process logically inherits the parent's address space and various execution attributes. Immediately copying the entire memory space would be expensive, so modern operating systems can generally use Copy-on-Write, in which the parent and child initially share existing physical pages and a page is copied only when either process modifies it. If a multithreaded process calls fork, only the calling thread is duplicated into the new process. Because the child inherits the existing address space and the states of synchronization objects, care is required regarding which functions can be used afterward and in what execution order.
On Windows-family systems, process creation commonly constructs the program to be executed, the initial address space, the process object, and the first thread together as part of a process-creation request. Despite these API-level differences, the operating system performs the same core role of configuring a new address space, execution context, and resource information.
When a process completes normally or terminates because of an error, the operating system records its exit status and cleans up resources such as memory, open files, and kernel objects. It may also provide a mechanism through which the parent process can inspect the termination result of a child.
In some operating systems, a minimal amount of management information remains after a process has stopped executing until its parent retrieves the termination status. In UNIX-family systems, a process that has finished running but whose parent has not yet collected its exit status is called a Zombie Process. Conversely, if a parent terminates before its child, another system process may assume the management relationship.
Process and Thread States
The operating system tracks whether a process or thread is currently able to execute and which resource or event it may be waiting for. Detailed state names and definitions differ among operating systems, but they can generally be classified as follows:
| State | Meaning |
|---|---|
| Creation | Preparing the data structures and resources required for execution |
| Ready | Able to execute but waiting to be assigned a CPU |
| Running | Currently executing instructions on a CPU |
| Waiting | Waiting for an event such as input/output, a lock, or a timer expiration |
| Stopped | Execution has been suspended by debugging, job control, or another mechanism |
| Terminated | Execution has finished and the process is awaiting resource cleanup or collection of its exit status |
A running thread may become unable to continue using the CPU because of a system call, page fault, input/output request, or wait on a synchronization object. The operating system then changes the thread to a waiting state and assigns the CPU to another ready thread. When the awaited event completes, the thread moves back to the ready state.
Creation
↓
Ready ────────────────┐
↓ Scheduling │ Preemption
Running ──────────────┘
│
├── Termination → Terminated State
│
└── Input/Output or Event Wait
↓
Waiting
↓ Event Completion
Ready
A process as a whole is sometimes described as running or waiting, but in a multithreaded process, each thread may have a different state. One thread may be running on a CPU, another may be waiting for network input, and another may be waiting for a lock.
Allocation of CPU Resources
A physical CPU core can execute only a limited number of instruction streams at any given moment. When there are more runnable threads than CPU cores, the operating system uses CPU Scheduling to determine which thread runs, when it runs, and on which core.
By alternating among multiple threads over short intervals, the operating system makes each program appear to progress continuously. In a multicore environment, some threads can execute truly concurrently on different cores.
Scheduling may consider goals such as the following:
- Reducing the amount of time the CPU remains idle
- Increasing the number of jobs completed per unit of time
- Reducing the response time of interactive programs
- Distributing CPU time fairly among users and jobs
- Executing high-priority jobs first
- Meeting the timing constraints of real-time tasks
- Preserving locality in CPU caches and memory access
- Controlling power consumption and heat generation
- Balancing workloads across multiple CPU cores
These goals can conflict with one another. Allowing a long-running computation to continue reduces context-switching overhead but may delay the response of interactive programs. Conversely, dividing execution time into intervals that are too short may improve responsiveness but cause context switches so frequently that less CPU time remains for actual work.
Preemptive Scheduling
In Preemptive Scheduling, the operating system can interrupt a running thread and switch to another even if the current thread does not voluntarily release the CPU. Preemption generally occurs because of hardware timer interrupts, priority changes, or the readiness of a more important task.
A preemptive structure allows other programs to use the CPU even if one program enters an infinite loop or performs a long computation. Modern general-purpose desktop and server operating systems generally use preemptive scheduling.
In Non-Preemptive Scheduling, the current task may continue running until it terminates, enters a waiting state, or explicitly yields the CPU. This method is relatively simple to implement, but a single faulty task can delay the execution of other tasks for a long time. It may be used in some constrained embedded environments and cooperative runtimes.
Time Quantum and Priority
An operating system may assign each thread a fixed Time Quantum and switch to another thread when that quantum expires. Not every thread necessarily receives the same amount of CPU time. Execution order and allocation duration may differ according to task priority, past CPU usage, waiting time, and system policy.
A high priority helps important tasks run quickly, but if high-priority tasks remain continuously ready, lower-priority tasks may receive almost no execution time, resulting in Starvation. An operating system can mitigate this by increasing the priority of jobs that have waited for a long time or dynamically adjusting priorities according to CPU usage.
In real-time scheduling, meeting task deadlines is more important than simple fairness. Linux's SCHED_DEADLINE policy uses parameters related to execution time, period, and deadline to provide CPU bandwidth to a task.
Context Switching
The process in which the operating system stops a running thread and begins executing another is called a Context Switch. The operating system saves the current thread's execution state, including its instruction position, stack pointer, and CPU registers, and restores the state of the next thread.
Thread A Running
↓ Save State
Scheduler Runs
↓ Select Next Thread
Restore Thread B State
↓
Thread B Running
When switching between different processes, the virtual address space and memory-translation information may also change. Modern CPUs internally cache address-translation results and data, so a switch can cost considerably more than simply changing a few registers.
A context switch does not itself perform the program's actual computation. Excessively frequent switching can therefore reduce overall throughput. However, it is also a necessary cost for maintaining responsiveness and fairness among multiple programs.
Multicore Systems and Processor Affinity
In a multicore system, the scheduler must decide not only which thread to run, but also on which core it should execute. Keeping a thread on the core where it previously ran increases the possibility of reusing code and data that remain in that core's cache. This is called Processor Affinity.
However, if work accumulates on a specific core, the system may fail to use the entire CPU evenly, so the scheduler can migrate workloads to other cores. In a NUMA system, the cost of memory access differs according to the physical location of the CPU and memory. The operating system may therefore attempt to place a thread on a processor close to the memory used by that thread. Windows also uses policies in NUMA environments that attempt to improve performance by placing threads on processors belonging to the same node as the memory they use.
Execution Context and Address Space
The addresses used by a program generally do not directly represent actual locations in physical RAM. The operating system provides each process with an independent Virtual Address Space and uses the CPU's memory management unit and page tables to translate virtual addresses into physical addresses.
Process Virtual Address
↓
Page Table
↓
Actual Location in Physical Memory
Each process can behave as though it has its own contiguous address space, even though its contents may be distributed across multiple locations in physical memory. Linux page tables are also described as a hierarchical structure that maps virtual addresses visible to the CPU to physical addresses used on the memory bus.
A virtual address space generally consists of areas such as the following:
- Executable machine code
- Read-only constants
- Initialized global data
- Uninitialized global data
- A dynamically allocated heap
- Shared libraries and memory-mapped regions
- The stack of each thread
- Reserved regions used by the operating system and architecture
High Addresses
┌──────────────────────┐
│ Stack │
│ ↓ │
├──────────────────────┤
│ Memory-Mapped Area │
│ Shared Libraries │
├──────────────────────┤
│ ↑ │
│ Heap │
├──────────────────────┤
│ Global and Static │
│ Data │
├──────────────────────┤
│ Program Code │
└──────────────────────┘
Low Addresses
This diagram is a simplified representation of the general concept. Actual growth directions, address ranges, and region placement differ according to the operating system, executable format, architecture, and security policy.
An important purpose of a virtual address space is process isolation. Even if a virtual address used by one process has the same numeric value as an address used by another, the two addresses can map to different physical pages. A process generally cannot directly access memory belonging to another process without permission.
In addition to isolation, virtual addressing supports the following functions:
- Providing a logical address space larger than actual physical memory
- Using physically separated memory as though it were one contiguous region
- Mapping files directly into an address space
- Sharing the same code and data among multiple processes
- Setting read, write, and execute permissions for individual memory regions
- Copy-on-write
- Delayed allocation that assigns physical memory only when needed
- Improved security through address space layout randomization
In Windows, each process also has an independent virtual address space, and every thread in the same process can access that address space.
Virtual Memory and Paging
Virtual Memory is a management system that separates the virtual addresses used by a process from actual physical memory. The operating system manages memory in fixed-size units called Pages and maps virtual pages to physical page frames.
When a process reads from or writes to a virtual address, the CPU uses page tables to locate the physical page associated with that address. To accelerate address translation, the CPU can store recently used translation results in a Translation Lookaside Buffer.
Virtual Address
↓
Virtual Page Number + Offset Within Page
↓
Page Table Lookup
↓
Physical Page Frame + Offset Within Page
↓
Physical Address
A page-table entry may contain not only the location of a physical page, but also state information such as read, write, and execute permissions, whether user-mode access is allowed, and whether the page is currently present in physical memory.
The operating system may not immediately assign physical memory to the entire amount of virtual memory requested by a process. The method of preparing physical memory only when a page is first accessed is called Demand Paging. Linux's memory-management subsystem also handles virtual memory, demand paging, user-space and kernel memory allocation, and file mapping.
Page Faults
When a process accesses a virtual page that does not currently have a valid physical mapping or does not permit the requested access, the CPU raises a Page Fault. A page fault does not always indicate a program error.
Examples of normal page faults include the following:
- Allocating a physical page for anonymous memory when it is first accessed
- Loading a required section of an executable file or shared library
- Reading a memory-mapped file page that is not currently in memory
- Creating a private page when a copy-on-write page is modified
- Reloading a page that had been moved to storage
If the operating system can resolve the request, it updates the page table and re-executes the interrupted instruction. If it cannot resolve the request, such as when a process accesses a nonexistent address or attempts to write to a read-only page, the operating system may deliver an error signal or exception to the process and terminate the program.
Physical Memory and Working Sets
Not every page in a virtual address space is always present in physical memory. The collection of pages that a process has recently used and that are currently resident in physical memory can be called its Working Set. In Windows, a working set is also defined as the set of recently referenced pages in a process's virtual address space and may include both shared and non-shared data.
When sufficient physical memory is available, frequently used pages can remain in RAM for fast access. As memory pressure increases, the operating system may reclaim less frequently used pages, discard pages that can be reloaded from files, and, if necessary, move some anonymous memory to a Swap Space on storage.
Because storage devices are much slower than RAM, system performance can decline sharply if required pages continuously move between physical memory and storage. The repeated replacement of pages because the set required by a workload is larger than available physical memory is called Thrashing.
Page Replacement
When physical memory is insufficient, the operating system must decide which pages to reclaim. Theoretical Page Replacement Algorithms include the following:
- FIFO, which replaces the oldest page first
- LRU, which selects the page that has not been used for the longest time
- Clock-family methods that use recent-access information
- An optimal algorithm that selects the page that will not be used for the longest future interval
Because future memory accesses cannot be known exactly, the optimal algorithm is mainly used as a reference for comparison. Real operating systems use complex policies combining information such as recent access, whether a page has been modified, whether it is file-backed or anonymous memory, per-process priority, and current memory pressure.
An unchanged page that can be read again from a file can be discarded without being written elsewhere. In contrast, modified anonymous pages may need to be written to swap space before they can be reclaimed.
Memory Allocation
Operating-system memory management can be divided into providing a virtual address space to a process and assigning actual physical pages. An internal allocator such as malloc, new, or a language-runtime allocator may acquire a large memory region from the operating system and divide it into smaller objects.
Application Object Allocation Request
↓
Language Runtime or Memory Allocator
↓ When Necessary
Virtual Memory Request to Operating System
↓
Reserve Virtual Address Region
↓ On Access
Allocate Physical Pages
Therefore, creating a single object in a program does not necessarily cause one system call. A typical memory allocator reuses regions obtained from the operating system and requests additional space only for large allocations or when existing memory is insufficient.
A virtual address region may distinguish between merely reserving an address range and connecting that range to actual physical storage. The precise meanings of reservation and commitment differ among operating systems and platforms, but this distinction allows a program to reserve a large contiguous address space while assigning physical resources only to the portions actually used.
Memory regions can be connected not only to anonymous memory, but also to files and devices. Linux's mmap creates a new mapping in the calling process's virtual address space. When a file is mapped, a program can read and write file data through ordinary memory-access instructions, while the operating system handles actual input/output using the page cache and page faults.
Shared Memory
Although process address spaces are isolated by default, the operating system can explicitly map the same physical pages into the virtual address spaces of multiple processes. This is called Shared Memory.
Process A Virtual Address ─┐
├── Same Physical Memory
Process B Virtual Address ─┘
Shared memory allows multiple processes to access data without additional copying, making it efficient for exchanging large amounts of data. POSIX shared memory also enables processes to exchange information through the same memory region by mapping a shared-memory object into each process's virtual address space.
However, if multiple processes modify the same data concurrently, race conditions can occur just as they can with memory shared among threads. Synchronization using mutexes, semaphores, atomic operations, or a clearly defined single-writer structure is therefore required.
Read-only pages containing program code and shared libraries can also be physically shared among multiple processes. Although each process sees them at an independent virtual address, mapping those addresses to the same physical pages reduces memory usage.
Resource Limits and Usage Management
An operating system can not only allocate CPU and memory, but also limit and measure the amount of resources that a particular user or process may use.
Managed resources may include the following:
- CPU time and CPU usage percentage
- Physical and virtual memory
- Number of processes and threads that can be created
- Number of files that can be opened
- Disk usage
- Input/output bandwidth
- Network bandwidth
- Access to specific CPUs and NUMA nodes
- Real-time scheduling privileges
Resource limits reduce the likelihood that one program will monopolize memory or CPU resources and interfere with other programs. In multi-user servers and container environments, they are important for separating the resources available to each user or service and measuring usage.
Linux Control Groups are a kernel feature that organize processes into hierarchical groups and make it possible to limit and measure usage of resources such as CPU, memory, and input/output.
The result of exceeding a resource limit depends on the resource type and policy. Additional memory allocation may fail, the CPU execution rate of a task may be reduced, or, under severe memory pressure, the operating system may terminate certain processes.
Relationship Between Execution and Resource Management
Processes and threads, CPU scheduling, and memory management are not independent functions. To execute a thread, the operating system must prepare the thread's CPU context and the process's address space. If a required memory page is absent during execution, it must handle a page fault. If the thread waits for input/output or memory, the operating system assigns the CPU to another thread.
Program Execution Request
↓
Create Process and Virtual Address Space
↓
Create Initial Thread
↓
Register in Scheduler Ready Queue
↓
Assign CPU
↓
Execute Instructions and Translate Virtual Addresses
↓
Page Fault, Input/Output, or System Call May Occur
↓
Place Thread in Waiting State if Necessary
↓
Assign CPU to Another Thread
↓
Return to Ready State After Event Completion
The operating system repeats this process so that multiple programs can share a limited number of CPU cores and a limited amount of physical memory. A process provides an independent execution environment for each program, a thread represents an actual flow of execution, and the scheduler distributes CPU time. Virtual memory isolates the address spaces of processes while allowing physical memory to be arranged and shared flexibly.
These abstractions allow a program to operate without directly controlling the number of CPU cores, the actual locations of physical pages, or the execution states of other programs. At the same time, the operating system must continually make policy decisions involving fairness, responsiveness, throughput, memory usage, and isolation.
CPU scheduling algorithms and page-replacement policies do not have one optimal solution for every environment. Interactive personal computers, large-scale servers, battery-powered mobile devices, and real-time control systems have different goals. Actual operating systems therefore combine multiple policies to manage execution and resources according to task priority, execution characteristics, hardware structure, and system load.
Concurrency and Communication
An operating system provides an environment in which multiple processes and threads can execute during overlapping periods of time. Even on a single CPU core, multiple tasks can make progress in turn if the operating system rapidly switches between execution targets. On a multicore system, multiple execution flows can actually perform instructions at the same time. This relationship between executing tasks is called Concurrency, while the physical execution of multiple computations at the same instant can be distinguished as Parallelism.
Concurrency is necessary for using CPUs and input/output devices efficiently and improving program responsiveness. A web server can process requests from multiple clients together, while a graphics program can separate screen input, rendering, and file input/output into different execution flows. Inside an operating system, multiple CPUs, devices, and interrupt handlers may also access kernel data structures concurrently.
However, when multiple execution flows share data and devices, results can vary depending on execution order. Operating systems and programs coordinate access to shared resources using mechanisms such as Mutexes, Semaphores, condition variables, atomic operations, and message passing. When processes occupy separate address spaces, they exchange data and notify one another of execution states through Inter-Process Communication. POSIX also requires synchronization operations to define the relationship between reads and writes when multiple execution flows access the same memory location.
Concurrently Executing Tasks
↓
Access Shared Resources
↓
Coordinate Execution Order and Visibility
├── Locks and Condition Variables
├── Semaphores and Events
├── Atomic Operations
└── Message Passing
↓
Safe Data Sharing and Communication
Concurrency and Parallelism
Concurrency is a structure in which two or more tasks make progress during overlapping periods of time. The tasks do not necessarily have to execute at the same instant. Even on a single core, the operating system can alternate between tasks so that one task performs computation while another waits for input/output.
Parallelism is the state in which two or more tasks actually execute at the same instant on multiple CPU cores or processing units.
Concurrency
CPU 1: Task A → Task B → Task A → Task C
Parallelism
CPU 1: Task A ───────────────
CPU 2: Task B ───────────────
CPU 3: Task C ───────────────
Concurrency does not always mean parallel execution, while a parallel program assumes concurrency among multiple tasks. The operating system places runnable threads on CPUs through scheduling, but the program and runtime determine how work is divided and which data is shared.
In operating-system studies, concurrency is treated as a core subject alongside CPU virtualization and persistent storage. Errors that occur when multiple execution flows access shared state are not merely scheduling problems, but also involve program correctness, memory models, and synchronization rules.
Shared State
Threads in the same process generally share a virtual address space, global variables, heap objects, and open files. Multiple processes can also access the same state through shared memory, files, kernel objects, devices, and network connections.
Shared state is not inherently incorrect. The problem is that one execution flow may access the same value while another is reading or modifying it.
Consider the following increment operation:
counter = counter + 1
Although it appears to be a single operation in source code, its actual execution may be divided into multiple steps:
1. Read the value of counter.
2. Add 1 to the value.
3. Store the result in counter.
If two threads perform this operation concurrently while counter has a value of 10, the following order is possible:
Thread A: Reads 10 from counter
Thread B: Reads 10 from counter
Thread A: Stores 11
Thread B: Stores 11
Although two increments were performed, the final result is 11 rather than 12. Each thread's individual operations executed normally, but the operations interleaved and produced an incorrect overall result.
Race Conditions
A Race Condition is a situation in which multiple execution flows access shared state and the program's result changes according to the specific execution order or timing.
Race conditions can occur in resources such as the following:
- Shared variables and data structures
- The current position and contents of a file
- Memory allocators
- Process and thread management lists
- Device command queues
- Network connection state
- Databases and transactions
- File-system metadata
- Kernel scheduling data structures
A race condition does not always immediately cause a visible error. A program may behave as expected during most executions but fail only under particular timing conditions, system loads, CPU counts, or compiler optimizations. For this reason, concurrency errors are often difficult to reproduce and diagnose.
Protecting all code that modifies shared state with one global lock can prevent some race conditions, but it also removes the advantages of concurrent execution and increases the risks of lock contention and deadlock. The design must therefore first determine which state should be shared and which operations must be treated as a single atomic unit.
Critical Sections
A Critical Section is a region of code that must be protected so that only a limited number of execution flows can enter it at the same time in order to preserve the consistency of a shared resource.
Acquire Lock
↓
Read or Modify Shared Data
↓
Release Lock
The property that allows only one thread at a time to enter a critical section is called Mutual Exclusion. The purpose is to make multiple instructions in the critical section appear to other execution flows as though they were performed as one operation without an observable intermediate state.
Mutual-exclusion algorithms and synchronization mechanisms generally consider conditions such as the following:
- No more than one execution flow should enter the protected region at the same time.
- When no one is using the critical section, a task that is able to enter should not wait indefinitely without reason.
- Starvation, in which a particular execution flow is continually denied access, should be prevented as much as possible.
- CPU time wasted on waiting should be reduced.
- The mechanism should operate correctly under interrupts and in multicore environments.
Making a critical section too large can simplify protection of shared resources, but other tasks may have to wait for a long time. Dividing it too finely can increase the number of locks and make it difficult to preserve the correctness of operations that must update several related states together.
Atomicity
Atomicity is the property that an operation appears from the outside to have been completed entirely or not performed at all, without being divided into smaller observable intermediate steps.
Some simple reads and writes can be performed atomically by hardware, but not every variable access is automatically atomic. This can depend on the size and alignment of the value, processor architecture, and the language's memory model. Even if one read and one write are each atomic, a larger operation composed of several such operations may not be atomic.
A CPU may provide Atomic Operations such as the following:
- Exchanging values
- Comparing a value and conditionally replacing it
- Atomically incrementing or decrementing a value
- Setting or clearing specific bits
Operating systems and runtimes can use these hardware operations to implement locks, semaphores, reference counting, and lock-free data structures.
Using atomic operations does not solve every synchronization problem. Maintaining consistency among several related variables or modifying a complex data structure may require a larger critical section and memory-ordering rules.
Memory Visibility and Ordering
In a multicore processor, each core uses caches and write buffers, while compilers and CPUs can reorder instructions that they determine to be independent in order to improve performance. Therefore, it cannot be assumed that when one thread writes a value to memory, another thread will necessarily observe that value immediately or in the same order.
A Memory Model defines matters such as the following:
- Which reads and writes are atomic
- When a write by one execution flow becomes visible to another
- The extent to which compilers and CPUs may reorder operations
- Which ordering relationships are established by locks and atomic operations
- The meaning of a program when a data race occurs
Changes made by a thread before releasing a lock must be observable by another thread that subsequently acquires the same lock. This relationship provides not only mutual exclusion but also memory visibility. POSIX synchronization rules similarly establish ordering between memory writes in one execution flow and reads in another through synchronization operations such as mutex operations.
Simply reading a variable repeatedly does not guarantee that a change made by another thread will be observed safely. Shared state must use atomic operations or synchronization objects provided by the language and operating system.
Mutexes
A Mutex is a mutual-exclusion synchronization object that can be owned by only one thread at a time.
Thread A: Acquire Lock → Use Shared Resource → Release Lock
Thread B: Wait → Acquire Lock
If another thread already owns the mutex when an acquisition is attempted, the calling thread may wait until the lock is released. Depending on the implementation, it may repeatedly test the lock for a short time before sleeping, or enter an operating-system waiting state immediately.
The following rules generally apply to a mutex:
- The thread that acquires the lock becomes its owner.
- Other threads do not access the protected resource until the lock is released.
- The owner releases the lock when the operation is complete.
- Every access path must follow the same locking rules.
A Windows mutex can also be owned by only one thread at a time and therefore provides mutual exclusion for shared resources. If multiple processes open a synchronization object with the same name, it can also be used for inter-process synchronization.
A POSIX mutex is primarily used to synchronize threads sharing memory within the same process. However, if the process-shared attribute is specified and the mutex is placed in shared memory, threads in multiple processes can use it together.
If an error or early return occurs while a lock is held, the lock may never be released. To prevent this, languages and libraries may provide structures that automatically release the lock when a scope ends.
Spinlocks
A Spinlock is a synchronization mechanism in which an execution flow repeatedly checks the lock state until it can acquire the lock.
while lock acquisition fails:
continue checking
Because it continues consuming CPU time while waiting, it is inefficient for locks that may be held for long periods. However, it can be advantageous when the lock is held for a very short time and the cost of putting the current thread to sleep and waking it again would be greater.
Spinlocks may be used in operating-system kernels and very short critical sections on multicore systems. This is because ordinary sleeping mutexes cannot be used in interrupt context or in situations where scheduling is unavailable.
On a single core, if the currently running thread spins while waiting for a lock held by another thread, the lock owner may never receive an opportunity to run. Whether a spinlock can be used therefore depends on preemption, interrupts, CPU count, and the kernel execution context.
Read-Write Locks
A Read-Write Lock is a synchronization object that permits multiple concurrent readers but requires exclusive access for writers.
Read Lock
- Can be acquired by multiple threads together
Write Lock
- Can be acquired by only one thread
- Cannot coexist with a read lock
When reads are frequent and modifications are rare, a read-write lock may provide greater concurrency than a regular mutex. However, its management is more complex, and a writer may experience starvation if readers continue arriving. Conversely, a writer-preference policy may increase delays for readers.
If read operations are extremely short or the proportion of writes is high, the additional management cost of a read-write lock may make it less efficient than a regular mutex.
Semaphores
A Semaphore is a synchronization mechanism that uses an integer value to represent the number of available resources or the number of events that have occurred.
Its basic operations can be described as follows:
Wait Operation
If the value is greater than 0, decrease it by 1 and proceed
If the value is 0, wait until progress becomes possible
Signal Operation
Increase the value by 1
Wake a waiting execution flow if necessary
A semaphore with an initial value of 1 can coordinate access to a single resource, but it does not have exactly the same meaning as a mutex. A mutex has an ownership concept, while the execution flow that waits on a semaphore and the one that signals it can generally be different.
A counting semaphore with an initial value greater than 1 can limit the number of identical resources that may be used concurrently.
4 Available Connections
↓
Semaphore Initial Value: 4
Task Uses a Connection
↓
Decrease Value
Task Returns a Connection
↓
Increase Value
POSIX defines semaphores for synchronization between processes or threads. An unnamed semaphore can be placed in shared memory, while a named semaphore is an operating-system object with an independent name that can be opened by multiple processes.
A Windows semaphore also maintains a count between zero and a defined maximum value and limits the number of threads that can access a shared resource concurrently.
Condition Variables
A Condition Variable is a synchronization object that causes a thread to wait until a particular state condition becomes true. A condition variable is generally used together with a mutex that protects shared state.
Acquire Mutex
while condition is false:
Wait on Condition Variable
└── Release Mutex While Waiting
└── Reacquire Mutex After Waking
Use Shared State
Release Mutex
When waiting on a condition variable, the transition from checking the state to entering the waiting state must be atomic so that a signal is not missed between those operations. The wait function releases the mutex while putting the thread to sleep and reacquires the mutex when the thread wakes.
A condition-variable signal is not the state itself. After waking, a thread must check the protected condition again because another thread may have consumed the state first, or the thread may have awakened for reasons unrelated to the condition. POSIX similarly defines a condition variable as a synchronization object that allows a thread to suspend execution repeatedly until an associated condition becomes true.
In the POSIX model, mutexes correspond to short mutual-exclusion operations, while condition variables correspond to waiting for relatively long or indeterminate conditions. Their combined use is presented as a fundamental thread-synchronization structure.
Events and Signal Objects
An Event is a synchronization object that notifies one or more waiting execution flows that a particular occurrence has taken place.
An event can have one of two states:
Non-Signaled State
- Waiting threads continue waiting
Signaled State
- Waiting threads become runnable
Windows provides manual-reset events and auto-reset events. A manual-reset event can wake multiple waiting threads and remains signaled until it is explicitly reset. An auto-reset event generally wakes one thread and then automatically returns to the non-signaled state.
Events can be used in situations such as the following:
- Notification of asynchronous input/output completion
- Notification that a task has started or finished
- Waiting for initialization of multiple tasks to complete
- Delivering a shutdown request
- Notification of state changes between producers and consumers
An event does not itself carry the data. The actual data can be stored in shared memory or a queue, while the event merely indicates that the data is available.
Barriers and One-Time Initialization
A Barrier is a synchronization mechanism that causes multiple execution flows to wait until all of them have reached a particular point.
Thread A ─── Reaches Barrier ─── Waits
Thread B ───────── Reaches Barrier ─── Waits
Thread C ───────────── Reaches Barrier
↓
All Proceed to Next Stage
It can be used when parallel computation is divided into multiple stages and the next stage must not begin until every task in the previous stage has completed.
One-Time Initialization ensures that initialization of a shared object or global state is performed exactly once during the entire lifetime of a program. Even if multiple threads call the initialization function concurrently, only one thread performs the initialization and the others wait for completion.
Simply checking a Boolean value that indicates whether initialization has completed can create a race condition between the check and the initialization. An operating-system or runtime-provided one-time initialization facility should therefore be used.
Producers and Consumers
The Producer-Consumer Problem is a representative synchronization problem in which one or more producers create data and one or more consumers process it.
Producer
↓ Add Data
Shared Buffer
↓ Remove Data
Consumer
If the buffer has a limited size, the following conditions must be coordinated:
- A producer waits when the buffer is full.
- A consumer waits when the buffer is empty.
- Multiple producers and consumers must not corrupt the buffer structure through concurrent access.
A mutex can protect the buffer itself, while condition variables can represent the conditions that the buffer is not empty and not full. Alternatively, two semaphores can represent the number of empty slots and the amount of available data. POSIX counting semaphores are also described as synchronization mechanisms well suited to resource-counting problems such as producer-consumer systems.
Similar structures are used in operating-system input/output queues, network packet queues, task schedulers, and logging systems.
Deadlocks
A Deadlock is a state in which two or more execution flows each wait for a resource held by another, leaving none of them able to make further progress.
The following situation is an example:
Thread A
Acquires Lock 1
Waits for Lock 2
Thread B
Acquires Lock 2
Waits for Lock 1
Each thread waits for the other to release a lock, but neither can progress to the point where it would release the lock it already holds.
The conditions under which a deadlock occurs are generally described as follows:
- Mutual Exclusion: A resource can be used by only one execution flow at a time.
- Hold and Wait: An execution flow holds one resource while waiting for another.
- No Preemption: A resource held by another execution flow cannot be forcibly taken away.
- Circular Wait: Multiple execution flows form a cycle in which each waits for a resource held by the next.
A deadlock can be prevented by removing one or more of these conditions.
Representative prevention methods include the following:
- Acquire every lock in a defined global order.
- Request multiple resources at once.
- If lock acquisition fails, release already acquired locks and try again.
- Place a timeout on lock waits.
- Reduce shared state and use message passing.
- Protect related state with a single lock.
- Use lock-free data structures or transactions.
Using a consistent lock order is a practical way to eliminate circular waits. OSTEP's analysis of concurrency errors also identifies acquiring multiple locks in different orders as a representative cause of deadlock.
An operating system does not automatically resolve every deadlock in user programs. Databases and some resource-management systems may analyze wait relationships, detect deadlocks, and cancel one operation, but with ordinary thread locks, the program must design its own prevention and recovery policies.
Starvation and Livelock
Starvation is a state in which a runnable task exists but is continually bypassed by other tasks and therefore effectively cannot obtain the resource or CPU time it requires.
It can occur when high-priority tasks continuously arrive or when read locks are continuously acquired so that a writer cannot proceed. It can be mitigated through fair waiting order, priority adjustment, or raising the priority of tasks that have waited for a long time.
Livelock is a state in which multiple execution flows are not blocked but continue changing state in response to one another without completing useful work.
Thread A: Yields the resource to avoid conflict
Thread B: Yields the resource at the same time
Threads A and B: Retry
The same process repeats
Repeated collisions can be reduced by adding randomized delays before retrying or assigning priority to one side.
In a deadlock, execution flows stop while waiting. In a livelock, they continue executing but make no progress.
Priority Inversion
Priority Inversion is a situation in which a high-priority task waits for a resource held by a low-priority task, while a medium-priority task prevents the low-priority task from running, causing the high-priority task to be delayed for a long time.
Low-Priority Task
Holds Lock
High-Priority Task
Waits for the Same Lock
Medium-Priority Task
Continues Running Before the Low-Priority Task
This can be mitigated through Priority Inheritance, which temporarily gives the low-priority lock owner the higher priority, or through a priority-ceiling method that raises the task to a predefined priority when it acquires the lock. POSIX mutex attributes may include synchronization properties for priority inheritance and priority ceilings.
Priority inversion is especially important in real-time operating systems because it can cause a task to miss its deadline.
Lock Contention and Scalability
Lock Contention occurs when multiple execution flows frequently attempt to acquire the same lock. Because only one can use the critical section at a time, increasing the number of CPU cores may stop improving performance or may even reduce it.
Methods for reducing contention include the following:
- Divide shared state into multiple parts and use a separate lock for each.
- Use read-only data and immutable objects.
- Use per-thread or per-CPU data and combine it later.
- Avoid input/output or long computations inside a critical section.
- Assign one owner to a data structure and request operations through messages.
- Use atomic operations or lock-free algorithms.
- Use copy-on-write and version-based reads.
Increasing the number of locks can reduce contention, but it also makes lock ordering and data-consistency management more complex. Lock granularity is therefore a design choice involving both performance and correctness.
Lock-Free Structures
A Lock-Free Algorithm allows multiple execution flows to modify a data structure using atomic operations rather than serializing every access through a traditional mutex.
A lock-free structure may aim to ensure that even if one operation is suspended, another operation can continue making progress. A stronger guarantee, known as wait-freedom, ensures that every operation completes within a bounded number of steps.
Lock-free methods can provide advantages such as the following:
- Reducing situations in which all progress stops because a lock owner is suspended
- Improving scalability in some high-contention environments
- Avoiding priority inversion and traditional deadlocks
However, implementation and verification are extremely difficult and must account for problems such as the following:
- Memory ordering
- Safe reclamation of removed objects
- The ABA problem, in which a value changes and later returns to the same value
- Starvation caused by repeated retries
- Differences among architecture-specific atomic instructions
General applications should therefore use verified concurrent data structures and operating-system or runtime libraries.
Inter-Process Communication
Because processes have separate address spaces, one process cannot directly read or write another process's ordinary memory. To exchange data or notify one another that work has started or completed, processes must use Inter-Process Communication mechanisms provided by the operating system. This is also called IPC.
Inter-process communication provides one or more of the following functions:
- Byte-stream transfer
- Message-oriented transfer
- Sharing memory regions
- Event and state notification
- Synchronization of resource access
- Transfer of permissions and identities between processes
- Communication with another process on the same computer or on a remote system over a network
Representative communication methods include the following:
| Method | Main Characteristics |
|---|---|
| Pipe | Generally a unidirectional byte stream |
| Named Pipe | Unrelated processes can connect through a name |
| Message Queue | Preserves message boundaries and stores messages in a kernel queue |
| Shared Memory | Maps the same physical memory into multiple processes |
| Socket | Supports local or network communication |
| Signal | Provides limited event notification |
| File | Persistent and simple, but requires consideration of synchronization and performance |
| Memory Mapping | Connects a file or shared object to an address space |
| Operating-System-Specific Object | Platform features such as ports, events, and mailslots |
The appropriate method depends on factors such as the size and structure of the transferred data, latency, bidirectionality, security, process lifetime, and the possibility of extending communication over a network.
Pipes
A Pipe is a kernel communication object that allows bytes written by one process to be read sequentially by another process.
Process A
↓ Write
Pipe Buffer
↓ Read
Process B
Traditional anonymous pipes are generally used between related processes, such as a parent and child, that can inherit or transfer file descriptors. A shell pipeline also connects the standard output of one program to the standard input of the next.
Program A | Program B | Program C
A pipe is generally a byte stream, so the boundaries between separate writes should not be assumed to remain unchanged when reading. If the communication requires a protocol, length fields or delimiters must be included explicitly.
A write operation may wait when the pipe buffer is full, while a read operation may wait when no data is available. When every write end has been closed, the reading side can detect the end of the stream. Attempting to write to a pipe from which all readers have disappeared may produce an error or signal.
Named Pipes
A Named Pipe has a name in a file-system path or operating-system namespace, allowing processes without a parent-child relationship to connect through the same name. On UNIX-family systems, it is also called a FIFO.
The name provides a connection point, but the actual data is not stored persistently like a regular file and instead passes through a kernel pipe buffer.
Windows named pipes can be used not only for local processes but, depending on configuration, also for client-server communication over a network. They can support bidirectional, message-oriented, or byte-oriented communication. The Windows IPC system provides multiple communication mechanisms, including pipes, file mappings, and mailslots.
Message Queues
A Message Queue stores data sent by a sender as discrete messages in an operating-system queue, from which a receiver removes them.
Sending Process
↓ Message
┌───────────────────────┐
│ Message 1 │
│ Message 2 │
│ Message 3 │
└───────────────────────┘
↓
Receiving Process
Unlike a pipe's byte stream, a message queue can preserve message boundaries. Some implementations also support message priorities, asynchronous notification, and timeouts.
The sender and receiver do not have to run at the same time, but queue storage is limited, and transferring large amounts of data may require copying between user space and kernel space.
Linux provides IPC systems including POSIX message queues and System V message queues. POSIX message-queue descriptors may also have implementation-specific properties that allow them to be integrated with file-descriptor-based monitoring systems.
Shared Memory
Shared Memory is a communication method that maps the same physical memory region into the virtual address spaces of multiple processes.
Process A Address Space ─┐
├── Shared Physical Pages
Process B Address Space ─┘
Because data does not have to be repeatedly copied through a pipe or message queue, shared memory is useful for communication involving large data sets and low latency.
However, the operating system only arranges for the memory region to be shared. It does not automatically make the data structures inside that region safe. If several processes modify the same data, process-shared mutexes, semaphores, atomic operations, or other synchronization mechanisms are required.
Windows file mapping can also connect the same file-backed or page-file-backed region to the address spaces of multiple processes and use it as shared memory. Microsoft documentation explains that file mapping is an efficient form of local IPC, but synchronization between processes, such as semaphores, is required to prevent data corruption.
The following matters must be defined separately in shared-memory communication:
- The data structure stored in the memory region
- The process responsible for initialization
- Data ownership
- Read and write order
- Recovery when a process terminates abnormally
- Structure-version and size compatibility
- Access permissions
- Cache and memory ordering
If a process terminates while holding a shared lock, other processes may wait forever. Some operating systems and synchronization APIs provide features such as robust mutexes that can detect owner termination, but the program remains responsible for restoring consistency in the shared data structure. POSIX also handles cases in which a mutex-owning thread terminates according to the mutex type and recovery policy.
Sockets
A Socket is an interface for exchanging data between two communication endpoints. It can be used between processes on the same computer or between processes on different computers through a network.
Major socket types include the following:
- Connection-oriented byte streams
- Connectionless datagrams
- Local-domain sockets
- Network-domain sockets
Local Communication
Process A
↓
Local Socket
↓
Process B
Network Communication
Client
↓ Network
Server Socket
↓
Server Process
Some platforms allow local sockets to transfer operating-system resources such as process credentials and file descriptors while communicating within the same system. Network sockets provide remote communication through protocols such as TCP and UDP.
Sockets are highly general-purpose, but the application must handle message formats, serialization, partial reads and writes, connection termination, errors, and reconnection.
Signals
A Signal is a mechanism through which the operating system or another process asynchronously notifies a process of an event.
Signals can represent situations such as the following:
- A user's interruption request
- Invalid memory access
- Termination of a child process
- Timer expiration
- A change in terminal connection state
- A request to terminate the process
Signals can carry only limited information, and a signal handler may run at an arbitrary point in the program. It therefore cannot freely use ordinary functions and data structures. Signals are more suitable for event notification and control than for transferring complex data.
In a safer design, the signal handler changes only a minimal amount of state or forwards the event to a file-descriptor-based event loop, while the actual processing occurs in a normal execution context.
Files and Memory Mapping
A regular file can also be used as a means of communication between processes. One process writes data and another reads it. This method is simple and has the advantage that data remains after the processes terminate.
However, if multiple processes modify the same file, the following matters must be considered:
- File locking
- Atomic renaming
- Write ordering and buffer flushing
- Partially written data
- File-format versions
- Failure recovery
Memory mapping connects file contents to a process's address space so that they can be read and written through ordinary memory access. If multiple processes create shared mappings of the same file region, they can communicate in a manner similar to shared memory.
File-based communication is suitable when persistence is required or when processes do not need to execute simultaneously, but it may be more complex than pipes or sockets for exchanging small real-time messages.
Remote Procedure Calls
A Remote Procedure Call abstracts communication so that a function executing in another process or computer can be invoked as though it were a local function.
Client Function Call
↓
Serialize Arguments
↓
Process or Network Transfer
↓
Execute Server Function
↓
Serialize Result
↓
Return to Client
In reality, network latency, connection failures, server termination, duplicated messages, and timeouts can occur, so a remote procedure call cannot have exactly the same meaning as an ordinary local function call.
Operating systems and system services may use RPC-like message-based interfaces to communicate between internal components. In a microkernel architecture, file systems and device services run as separate processes, so efficient IPC has an important effect on operating-system performance.
Relationship Between Communication and Synchronization
Communication and synchronization may appear to be separate functions, but in practice they are closely connected.
Shared memory allows data to be exchanged quickly, but synchronization objects are required to coordinate access. Conversely, pipes and message queues provide a degree of synchronization through data delivery itself. A receiver can wait until data arrives, and a sender can wait until space becomes available in the queue.
Shared-Memory Method
Shared Data
+
Mutexes, Semaphores, and Events
Message-Passing Method
Message Transfer
=
Data Movement + Event Notification
Shared memory provides high performance and flexibility, but aliases, lifetimes, and synchronization must be managed directly. Message passing provides clearer separation between the states of different tasks, but can introduce data-copying, serialization, and queue-management costs.
Some systems use a hybrid structure in which actual data is stored in shared memory, while a pipe, event, or socket communicates only the location and readiness state of the new data.
Blocking and Non-Blocking Operations
A synchronization or communication operation may cause the calling execution flow to wait when the operation cannot be completed. This is called Blocking.
No Data Available to Read
↓
Move Thread to Waiting State
↓
Data Arrives
↓
Run Thread Again
A Non-Blocking operation returns an error or current state immediately if it cannot proceed, rather than waiting. The program may try again later or monitor the readiness of multiple communication objects together.
Non-blocking operations are useful in event-driven programs in which one thread manages many connections, but state machines, partial completion, and error handling can become complex. Asynchronous syntax such as async and await helps express state transitions in non-blocking input/output in a form similar to sequential code.
Blocking does not necessarily mean continuously consuming CPU time. An ordinary operating-system wait removes the thread from scheduling until the event occurs and then wakes it. In contrast, a spin wait continuously checks the state while remaining active on the CPU.
Event-Driven Concurrency
In Event-Driven Programming, one or a small number of threads wait for events on multiple input/output objects and execute handlers for events that become ready.
Event Loop
↓
Wait for Input/Output Readiness
↓
Identify Ready Connections
↓
Execute Corresponding Handler
↓
Wait Again
When many network connections spend most of their time waiting, this structure can reduce the cost of creating one thread per connection. However, if one handler consumes the CPU for a long time, processing of other events is delayed, so lengthy computations must be delegated to separate workers.
An event-driven structure can reduce shared-state and locking problems found in multithreaded systems, but it introduces the difficulty of managing task state across multiple callbacks and events. OSTEP also presents event-driven concurrency as an alternative that avoids some race conditions and deadlocks associated with thread- and lock-centered approaches.
Concurrency Inside the Operating System
Concurrency problems are not limited to user programs. An operating-system kernel can execute concurrently in multiple contexts such as the following:
- System calls running on different CPUs
- Kernel threads
- Hardware interrupt handlers
- Deferred-processing tasks
- Device-completion callbacks
- Process termination and resource cleanup
- Timers and the scheduler
The kernel must protect shared data structures such as process lists, page tables, file-system caches, network queues, and device states. The synchronization mechanism that can be used depends on whether the current kernel context may sleep, whether interrupts are enabled, and whether it can be preempted on the current CPU.
If data accessed by an interrupt handler is protected using an ordinary thread mutex, a problem can occur because interrupt context cannot sleep. Kernel-specific methods such as short spinlocks, interrupt disabling, atomic operations, and deferred processing are therefore used.
Waiting for user-space data or a slow device response while holding a lock can block other kernel operations for a long time. Lock scope and execution context are therefore especially important in kernel synchronization.
Protection of Inter-Process Communication
IPC objects are resources managed by the operating system and must not be accessible to arbitrary processes. The operating system can restrict access to IPC objects using users and groups, access control lists, namespaces, and security identifiers.
Access checks may include the following:
- Which processes may open shared memory
- Which users may connect to a named pipe
- Which processes may access a socket address
- Permission to read from or write to a message queue
- Permission to open a synchronization object or change its state
- Verification of another process's credentials
Windows named synchronization objects and file-mapping objects can also use security descriptors and access control lists to restrict access by other processes. When multiple processes share an object with the same name, both the object name and its permissions must be configured correctly.
Linux System V IPC and POSIX IPC objects can similarly control access through users, groups, permission bits, or file-system namespaces.
Data received through IPC should be treated as untrusted input even if it originated from another process on the same computer. Failure to validate message size, format, permissions, and state transitions can create security vulnerabilities across process boundaries.
Choosing Synchronization Mechanisms
Synchronization and communication mechanisms can be selected according to requirements such as the following:
| Requirement | Potentially Suitable Method |
|---|---|
| Short modification of shared data | Mutex or atomic operation |
| Wait until a particular state is reached | Mutex and condition variable |
| Manage a limited number of identical resources | Semaphore |
| Notify task completion | Event |
| Join multiple stages of parallel work | Barrier |
| Share large amounts of local data | Shared memory and synchronization objects |
| Simple byte stream | Pipe |
| Preserve message boundaries | Message queue or datagram socket |
| Common local and remote communication | Socket |
| Asynchronous event notification | Event, signal, or file-descriptor-based notification |
| Retain data after process termination | File or database |
No single method is best for every situation. Shared memory is fast but complex, while message passing strengthens separation but introduces copying and queue overhead. A spinlock may be appropriate for a very short kernel critical section but unsuitable for a long wait in a user program. A read-write lock may be advantageous only when reads greatly outnumber writes.
Concurrency Design Principles
To reduce concurrency errors, it is important to design data ownership and communication structures before adding synchronization objects afterward.
Major principles include the following:
- Reduce shared mutable state whenever possible.
- Use immutable data and value copying.
- Clearly define the lock that protects each shared resource.
- Maintain a consistent lock-acquisition order.
- Avoid long computations and input/output while holding a lock.
- Use condition variables in a structure that repeatedly checks the condition.
- Use verified synchronization primitives provided by the operating system.
- Consider abnormal termination of processes and threads.
- Handle timeouts, cancellation, and partial failures.
- Clearly define IPC message formats and versions.
- Validate received data and object permissions.
- Verify the absence of race conditions before optimizing performance.
A structure that eliminates concurrency can be better than complex synchronization. If only one thread or process modifies a particular data structure and other tasks submit requests through messages, the need for shared-memory locking can be reduced.
However, message queues and event loops also internally depend on operating-system synchronization and memory management. They do not completely eliminate concurrency problems, but move them into clearer boundaries and communication rules.
Summary
Concurrency is a fundamental capability that allows an operating system to overlap multiple execution flows and use multicore processors. Processes and threads make it possible to use CPUs and input/output devices efficiently, but differences in the order of access to shared state can cause race conditions, data corruption, and deadlocks.
Operating systems provide synchronization mechanisms such as mutexes, semaphores, condition variables, events, and atomic operations to coordinate access to shared resources and waiting for events. Processes exchange information across isolated address spaces through pipes, message queues, shared memory, sockets, signals, and file mappings.
Synchronization is not merely a mechanism that prevents more than one task from executing at a time. It defines execution order and memory visibility, represents resource quantities and state changes, and allows multiple tasks to cooperate safely. Inter-process communication likewise defines not only data transfer but also task initiation and completion, errors, and lifetime relationships.
The operating system provides these fundamental mechanisms, but the program and system design must determine which data is shared, in which order locks are acquired, and how failures are recovered. The central goal of concurrency and communication is therefore to control possible execution orders while reducing unnecessary serialization and allowing independent tasks to make progress safely.
Security and Isolation
An operating system must protect multiple users and programs sharing the same hardware so that they cannot arbitrarily modify one another's data or execution state. To achieve this, it combines mechanisms such as processor privilege levels, virtual address spaces, user accounts, access permissions, system calls, sandboxes, and virtualization to establish trust boundaries.
The fundamental goal of operating-system security is to prevent unauthorized subjects from reading, modifying, or using data and system resources. NIST defines a trusted operating system as one that ensures only subjects with the appropriate authorization can access, modify, or move data.
Resources protected by an operating system include the following:
- Processes and threads
- Virtual memory and physical memory
- Files and directories
- Devices and device drivers
- Network connections and ports
- User accounts and authentication information
- Inter-process communication objects
- The kernel and system services
- Cryptographic keys and security credentials
- Virtual machines and containers
An operating system does not trust every program equally. Ordinary applications run with restricted privileges, while only the kernel and certain system components are allowed to access hardware and system-wide resources. When a program requires additional privileges, it must go through system calls and permission-checking procedures provided by the operating system.
Users and Applications
↓ Authentication and Authorization
User Space
↓ System Calls
Kernel Permission Checks
↓
Files, Memory, Devices, and Networks
Protection and Security
Protection is the system that controls which resources a subject within an operating system may access and in what ways. Security is a broader concept that includes protection mechanisms as well as authentication, encryption, integrity verification, auditing, updates, and responses to attacks.
In operating-system protection, the entity performing an action can be classified as a subject, while the entity being accessed can be classified as an object.
| Category | Examples |
|---|---|
| Subject | User, process, thread, system service |
| Object | File, memory, device, socket, process, IPC object |
| Permission | Read, write, execute, create, delete, control |
| Policy | Which subject may access which object with which permissions |
A process can be a subject acting on behalf of a user while also being an object that other processes may access. Early research on operating-system protection also distinguished active subjects such as users and processes from protected objects such as files, devices, and other processes, and examined structures for preventing unauthorized access.
The presence of protection mechanisms does not automatically make an operating system secure. Incorrect permission settings, vulnerable system services, kernel defects, unsafe device drivers, and user errors can all cause security problems. To reduce these risks, an operating system combines multiple layers rather than relying on a single defensive mechanism.
User Mode and Kernel Mode
Modern processors can execute code at different privilege levels. Operating systems use this capability to separate ordinary programs from the kernel.
- In User Mode, applications can use only restricted instructions and their own address spaces.
- In Kernel Mode, core operating-system code can access all memory, devices, and processor-control features.
In Windows, applications run in user mode, while core operating-system components run in kernel mode. Many drivers operate in kernel mode, although some can run in user mode.
User Mode
- Ordinary Applications
- Restricted Address Space
- Limited Direct Hardware Access
- Privileged Instructions Unavailable
↓ System Call
Kernel Mode
- Kernel
- Memory Manager
- Scheduler
- File Systems
- Network Stack
- Some Device Drivers
If a user-mode program could directly modify page tables, disable interrupts, or manipulate arbitrary device registers, a single program could damage the entire system. These operations are therefore restricted as privileged instructions and performed by the kernel on behalf of programs.
When a system call occurs, the processor switches to kernel mode through a controlled entry point. The kernel checks the call number, arguments, user-memory addresses, and access permissions before processing the request and returning to user mode.
Defects in kernel mode have a greater impact than errors in user mode. Because kernel code and drivers can access the memory of other processes and system-wide resources, invalid memory access may lead to system failure or privilege escalation.
Address-Space Isolation
An operating system provides each user process with an independent Virtual Address Space. Even when two processes use the same numerical virtual address, the addresses can map to different physical memory locations.
In Windows, each user-mode process likewise has an independent private virtual address space, while kernel-mode code uses a separate shared system address space.
Process A
Virtual Address 0x1000
↓
Physical Page A
Process B
Virtual Address 0x1000
↓
Physical Page B
Page-table entries may include protection attributes such as the following:
- Whether user-mode access is permitted
- Read permission
- Write permission
- Execute permission
- Whether the page is currently valid
- Whether the page is shared
- Whether the page has been modified
A code region can be configured as read-only and executable, while an ordinary data region can be writable but non-executable. This makes attacks that attempt to execute data inserted into memory as machine code more difficult.
When a process accesses an unauthorized address or attempts to modify a read-only region, the processor raises an exception. The kernel determines whether the access can be resolved normally, as with demand paging or copy-on-write. If it cannot be resolved, the kernel reports an error to the process or terminates it.
Address-space isolation prevents accidental interference and some attacks between programs, but it is not a complete security boundary. A defect in the kernel or a device driver may allow access to another process's memory, and when processes explicitly map shared memory, that region becomes jointly accessible.
Users and Accounts
A User Account is a logical subject used by an operating system to distinguish the identities of people, services, and system tasks. A process generally inherits the security credentials of the user that started it.
An operating system may manage the following information for each user:
- User identifier
- Group membership
- Login credentials
- Home directory
- Permitted privileges
- Resource limits
- Security policies
- Audit information
A single person may use multiple accounts, and service accounts may exist without being used for direct human login. Assigning a separate account to each system service can ensure that even if the service is compromised, it can access only the resources permitted to that account.
A Group is a unit used to grant common permissions to multiple users. Instead of repeatedly assigning the same permissions to individual users, permissions can be assigned to groups according to roles or organizational structure.
An operating system distinguishes Authentication, which verifies the identity of the current user, from Authorization, which determines whether an authenticated user may perform a specific action.
Authentication
Who made the request?
Authorization
May that subject perform the requested action?
Passwords, security keys, biometric information, smart cards, and multi-factor authentication can be used for user authentication. Even when authentication succeeds, the user does not automatically gain access to every resource. Each object is still subject to permission checks according to its access policy.
Access Control
Access Control determines which operations a subject may perform on an object. When opening a file, controlling a process, or accessing a device, the operating system compares the current process's credentials with the object's security information.
Representative access permissions include the following:
- Read
- Write
- Execute
- Create
- Delete
- Change ownership
- Change permissions
- Control another process
- Use a device
- Use a network port
Discretionary Access Control
In Discretionary Access Control, the owner of an object can determine, within defined limits, which permissions are granted to other users and groups. UNIX-family owner, group, and other permissions and Windows access control lists are representative examples.
Traditional UNIX-family file permissions are classified as follows:
Owner Permissions
Group Permissions
Other-User Permissions
Each Permission
- Read
- Write
- Execute
For directories, read, write, and execute permissions can have different meanings from those for regular files. Execute permission can indicate permission to traverse paths within the directory.
Access Control Lists
An Access Control List records specific allow or deny permissions for multiple users and groups on a single object.
Document File
User A: Read, Write
User B: Read
Group C: Read
User D: Access Denied
This makes it possible to express more detailed policies than a simple owner, group, and other-user classification. However, when inherited rules and the ordering of allow and deny entries become complex, understanding the effective permissions may become difficult.
Mandatory Access Control
In Mandatory Access Control, system-wide security policies take precedence over a user's ability to freely change object permissions. Processes and objects may be assigned security levels, roles, or types, with access permitted only for approved relationships.
On Linux, the Linux Security Modules architecture allows security-policy implementations such as SELinux and AppArmor to be connected to the kernel. Apple's operating systems have also used kernel-level mandatory access-control mechanisms to construct application sandboxes. Apple's earlier operating-system architecture documentation also explains that MAC restricts process capabilities and provides application sandboxing.
Mandatory access control can impose additional restrictions even on processes with administrative privileges. However, because complex policies can block normal application behavior, policy design and diagnostic tools are important.
Principle of Least Privilege
The Principle of Least Privilege states that programs and users should receive only the minimum permissions required to perform their tasks.
For example, a simple web server does not need all of the following permissions:
- Read every user's files
- Access arbitrary devices
- Load kernel modules
- Create user accounts
- Change system settings
Allowing only access to the web-content directory and use of a limited network port reduces the range of resources available to an attacker even if the server is compromised.
Least privilege can be applied through methods such as the following:
- Running programs under ordinary user accounts
- Using a separate account for each service
- Allowing only required files and devices
- Using administrator privileges only temporarily
- Separating permissions by function
- Using sandboxes and containers
- Removing unnecessary privileges from child processes
- Separating privileged functions into a small independent service
Instead of granting privileges once and retaining them throughout the program's lifetime, a program may remove them after completing the required task. Examples include dropping administrative privileges after opening a network port or delegating privileged work to a small helper process.
Administrators and Privilege Escalation
Operating systems contain highly privileged accounts or security subjects capable of managing system-wide settings, users, devices, and security policies. On UNIX-family systems, this is traditionally the root account. On Windows, it includes administrator accounts and processes operating at a high integrity level.
If ordinary users always run programs with administrator privileges, application defects and malicious code can affect the entire system. Modern operating systems therefore perform ordinary work with restricted privileges and request separate authentication and approval only when necessary, such as when changing system settings.
Privilege Escalation is the process by which a process obtains greater privileges. It can be used for legitimate administrative work, but the same term also refers to attacks that exploit vulnerabilities to gain unauthorized privileges.
A secure privilege-escalation structure requires the following elements:
- Authentication of the requesting user
- A clear display of the action to be performed
- Privileges limited to the necessary scope
- Validation of user input
- Logging and auditing of the operation
- Revocation of privileges after completion
Highly privileged components should be kept as small as possible. Instead of running an entire user interface with administrator privileges, only actual system changes can be performed by a small privileged service.
Security Boundaries
A Security Boundary is an isolation point that prevents subjects in one area from directly accessing resources in another.
Representative operating-system security boundaries include the following:
- User mode and kernel mode
- Address spaces of different processes
- Ordinary users and administrators
- Applications and resources outside their sandboxes
- Guest operating systems and the hypervisor
- Virtual machines and the host
- Different security domains
- Trusted execution environments and the ordinary operating system
Not every logical separation constitutes a security boundary of equal strength. Merely separating process names or directory structures does not isolate memory or permissions. For a separation to qualify as a security boundary, a trusted component must enforce access across it.
Windows Virtual Secure Mode uses a hypervisor to create multiple Virtual Trust Levels and forms a separate security boundary that prevents processes in one trust level from accessing memory belonging to another. This can isolate assets such as passwords and Kerberos keys from the ordinary kernel environment.
Sandboxes
A Sandbox is an isolated environment that restricts the files, devices, networks, processes, and system functions a program can access in order to reduce the scope of damage if the program is compromised.
A sandbox begins with the assumption that the program is not trusted. It applies a policy that allows the program to perform its required tasks while preventing access to other resources.
Application
↓
Sandbox Policy
├── Access Only Specified Files
├── Use Only Permitted Networks
├── Use Only Restricted Devices
├── Limit Access to Other Processes
└── Restrict Kernel Functions
Apple's App Sandbox restricts access to system resources and user data according to entitlements declared by the application and is intended to contain damage when an application is compromised.
A sandbox policy can restrict the following elements:
- File-system paths
- Camera and microphone
- Location and contacts
- Network connections
- Communication with other processes
- Child-process creation
- System calls
- Device access
- User-interface control
- Debugging and process inspection
An application can gain limited access to restricted resources by asking the user to choose a file or by using a broker service provided by the operating system. macOS App Sandbox also blocks access to protected resources by default and expands the permitted scope through explicit mechanisms such as user-selected documents and application groups.
Unlike a separate virtual machine, a sandbox usually shares the same kernel. A kernel vulnerability may therefore allow escape from the sandbox boundary, and the sandbox itself requires correctly configured policies.
Capability-Based Security
Traditional access control manages permissions around users and objects, while Capability-Based Security uses an unforgeable reference or token representing permission to perform a specific operation on a specific object.
A File Descriptor obtained by opening a file or socket can also be viewed as a limited capability reference. Passing an already opened file descriptor to a child process or another process delegates access to a specific file without granting access to the entire file system.
A capability-based structure has advantages such as the following:
- Permissions can be limited to a specific object.
- An already authorized object can be used without a separate global name lookup.
- Only required permissions can be delegated to another process.
- Dependence on global administrator privileges can be reduced.
However, capability references must be managed carefully so that they are not transferred or inherited by unintended processes.
System Call Restrictions
User-mode programs use kernel functions through system calls. Blocking system calls that a program does not need reduces the actions available to an attacker exploiting a vulnerability.
A system call restriction policy can be configured in ways such as the following:
- Allowing only approved system calls
- Permitting only specific arguments and operations
- Restricting process creation and debugging
- Restricting file-system namespaces
- Restricting network address families
- Restricting device-control calls
Features such as Linux seccomp can be used as sandbox components that limit which system calls a process may execute. However, if the required system-call list is not configured accurately, the program may fail to work normally. If the permitted set is too broad, the protective effect may be reduced.
System call restrictions do not replace file permissions, address-space isolation, or network policies. They are generally combined so that an operation permitted by one layer can still be restricted by another.
Code Signing and Execution Trust
Code Signing is a technology used to verify that an executable, library, or driver was distributed by a particular signing entity and has not been modified since it was signed.
Apple describes code signing as a macOS security technology that authenticates the creator of an application and verifies whether the program has been accidentally or maliciously altered since signing.
Code signing can be used to verify the following:
- Code integrity
- Distribution identity
- Permitted privileges and entitlements
- Whether a driver is trusted
- Whether an update came from an authorized distributor
- Whether code can pass execution policy
A signature does not mean that the program itself is secure. Signed programs may still contain vulnerabilities or malicious behavior. Code signing primarily verifies the origin of the code and whether it has changed, while the safety of its actual behavior must be evaluated separately.
The Linux kernel can also cryptographically sign kernel modules and verify those signatures when loading them. Depending on policy, this can restrict the loading of unsigned or untrusted modules.
Secure Boot
Secure Boot is a system that verifies the integrity and trustworthiness of firmware, bootloaders, kernels, and initial system components in stages when a computer starts.
Hardware Root of Trust
↓ Verify Firmware
Bootloader
↓ Verify Kernel
Operating-System Kernel
↓ Verify System Components
Start User Space
If early boot code is modified by an attacker, later security checks performed by the operating system may also be bypassed. Secure boot establishes a chain of trust in which each stage verifies the signature or hash of the next stage.
Apple's platform-security documentation similarly explains that the secure boot chain, system security, and application-security features work together to verify that only trusted code and applications are executed.
Secure boot can restrict execution to code approved by the system, but on devices where users manage their own operating systems and keys, the owner may need a structure that permits changing the trust criteria.
Integrity and Execution Protection
An operating system can use various hardware and software mechanisms to protect running code and control flow.
Representative mechanisms include the following:
- Restricting execution of writable memory
- Address space layout randomization
- Stack protection values
- Control-flow protection
- Read-only kernel regions
- Kernel-module signing
- System-file integrity checking
- Hardware-based stack protection
- Kernel page-table isolation
Address Space Layout Randomization changes the locations of programs, libraries, stacks, and heaps between executions, making it more difficult for an attacker to predict the addresses of code and data.
Execution-prevention mechanisms restrict code execution from ordinary data pages. However, programs such as JIT compilers that generate code during execution must strictly transition memory between writable and executable states.
Windows can use features such as hardware-enforced kernel-mode stack protection to detect or prevent corruption of return addresses.
These mitigation techniques do not remove vulnerabilities themselves, but they make it more difficult to turn a vulnerability into arbitrary code execution or privilege escalation.
File and Data Protection
An operating system can provide the following protection mechanisms for files and storage devices:
- File ownership and access permissions
- Access control lists
- File encryption
- Full-disk encryption
- Secure deletion
- Integrity checking
- Change history
- Backup and recovery
- Read-only file systems
- Snapshots
Encryption makes it more difficult for unauthorized users to read data if a storage device is removed or a device is lost. However, when a user is logged in and the encryption key is active, operating-system and application permissions remain important.
File encryption and access control address different problems.
Access Control
On a Running System
Who may use the file?
Encryption
If the storage device or data is leaked
Can its contents be read?
If malicious code is already running with the user's permissions, it may be able to read encrypted files that the user can access. Encryption therefore cannot replace application isolation.
Auditing and Logging
Security Auditing is the system of recording and analyzing security-related actions performed by users and programs.
Audit records may include the following:
- Login and logout
- Authentication failures
- Use of administrator privileges
- File access and permission changes
- System-setting changes
- Service startup and shutdown
- Security-policy violations
- Device connections
- Program execution
- Network connections
Audit logs are used to investigate incidents, verify regulatory compliance, and detect ongoing attacks.
However, if passwords, encryption keys, or personal data are recorded directly in logs, the logs themselves can become a security risk. Log access permissions, retention periods, integrity, and remote transmission must therefore be managed together.
If an attacker obtains administrator privileges, local logs may be modified. Important systems may therefore transmit logs to a separate server or a storage system that is difficult to alter.
Updates and Vulnerability Response
Operating systems process large amounts of hardware, network input, complex file formats, and applications, so security vulnerabilities may be discovered over time. A secure operating system is therefore not merely one without vulnerabilities, but one that includes mechanisms for discovering and fixing vulnerabilities and safely distributing updates.
An update system should satisfy conditions such as the following:
- Verification of the distributor's signature
- Prevention of tampering during transmission
- Recovery after failure
- Prevention of an unbootable state
- Version and dependency management
- Rapid distribution of security fixes
- Prevention of malicious rollback to an earlier version
Because kernels, device drivers, and system libraries run with high privileges, their security updates are especially important. An operating system that has reached the end of support may no longer receive fixes for newly discovered vulnerabilities.
Automatic updates can protect large numbers of devices quickly, but critical industrial systems and servers may require compatibility testing, staged deployment, and recovery plans.
Virtualization
Virtualization is a technology that divides the resources of one physical computer into multiple logical execution environments or provides an abstract hardware environment different from the actual hardware.
In operating-system virtualization, a Hypervisor allocates CPUs, memory, interrupts, and devices to virtual machines. Each Virtual Machine behaves as though it has its own independent computer and can run a separate guest operating system.
Physical Hardware
↓
Hypervisor
├── Virtual Machine A
│ └── Guest Operating System A
├── Virtual Machine B
│ └── Guest Operating System B
└── Virtual Machine C
└── Guest Operating System C
A virtual machine can virtualize resources such as the following:
- Virtual CPUs
- Virtual memory
- Virtual disks
- Virtual network devices
- Virtual interrupts
- Virtual firmware
- Virtual graphics and peripheral devices
The guest kernel of a virtual machine has an address space and kernel state separated from those of other virtual machines. Even if one guest operating system is compromised, it cannot directly access other guests or the host when hypervisor isolation operates correctly.
However, virtual machines do not provide absolute isolation. Vulnerabilities in the hypervisor or virtual-device implementations, or incorrect permissions on management interfaces, can break the boundary.
Hypervisors
Hypervisors are generally divided into the following two forms.
Bare-Metal Hypervisors
A bare-metal hypervisor runs directly on hardware and manages virtual machines.
Hardware
↓
Hypervisor
↓
Multiple Guest Operating Systems
It is mainly used in data centers and server virtualization and can reduce dependence on a general-purpose host operating system.
Hosted Hypervisors
A hosted hypervisor runs as an application or kernel component of a general-purpose operating system.
Hardware
↓
Host Operating System
↓
Virtualization Program
↓
Guest Operating System
It is convenient for development, testing, and desktop environments, but depends more heavily on the host operating system's drivers, security, and resource management.
Actual products may use hybrid structures that do not fit perfectly into this classification. The important difference is which layer enforces isolation between virtual machines and where device and management services run.
Hardware-Assisted Virtualization
Modern CPUs provide virtualization instructions and separate execution modes so that a hypervisor can isolate guest operating systems efficiently.
Hardware-assisted features may include the following:
- Separation of guest and hypervisor execution modes
- Two-stage address translation
- Virtual interrupts
- Direct device assignment
- Input/output memory management units
- Virtual trust levels
- Memory encryption
With two-stage address translation, the guest operating system translates a guest virtual address into a guest physical address, after which the hypervisor translates it again into an actual host physical address.
Guest Virtual Address
↓ Guest Page Table
Guest Physical Address
↓ Hypervisor Address Translation
Host Physical Address
Early virtualization without hardware assistance had to intercept privileged instructions or dynamically translate code, but modern CPUs directly support many operations and thereby reduce virtualization overhead.
Virtual Machine Isolation
The main security advantage of virtual machines is that each guest uses a separate kernel. Process-based sandboxes and containers share the host kernel, while virtual machines generally maintain an independent kernel and system state for each guest.
Virtual machine isolation can provide boundaries such as the following:
- Separate kernel
- Separate page tables
- Virtual devices
- Separate boot process
- Separate users and file systems
- Virtual network boundaries
Hypervisor-based isolation can also separate security-sensitive assets from the ordinary operating-system kernel. Windows VSM similarly uses a hypervisor and Virtual Trust Levels to establish memory-protection boundaries.
Virtual-machine management interfaces have extremely high privileges. Because they may access virtual disks, memory snapshots, and virtual networks, management permissions must not be granted indiscriminately to ordinary users.
Containers
A Container is a form of operating-system-level virtualization that shares the host operating-system kernel while providing isolated views of processes and resources instead of running a complete separate guest kernel.
Physical Hardware
↓
Host Operating-System Kernel
├── Container A
│ ├── Processes
│ └── File-System Environment
├── Container B
│ ├── Processes
│ └── File-System Environment
└── Container C
├── Processes
└── File-System Environment
Containers generally combine the following mechanisms:
- Separation of resource views through Namespaces
- Resource limiting and measurement through Control Groups
- A separate root file system
- Capability and privilege restrictions
- System call filters
- Mandatory access control
- Virtual network interfaces
Linux namespaces abstract global system resources so that processes inside them appear to have independent resources, while changes in one namespace can be hidden from processes in another. Containers are a representative use of these namespaces.
Linux Namespaces
Linux namespaces can isolate resources such as the following:
- Process identifiers
- Mount points
- Network devices and addresses
- Host names
- User and group identifiers
- Inter-process communication objects
- Control-group views
- Some time information
Host
├── PID Namespace A
│ └── Process Numbers Begin at 1 Internally
├── Network Namespace A
│ └── Independent Interfaces and Routing
└── Mount Namespace A
└── Independent File-System Mount View
A user namespace can map an administrator user inside a container to an ordinary user identifier on the host. This allows a process to appear highly privileged inside the container while retaining only restricted privileges on the host.
Namespaces hide resources or provide separate views of them, but do not automatically limit resource consumption. CPU, memory, and input/output usage must be managed together with control groups.
Control Groups
Control Groups are a Linux kernel feature that groups multiple processes and limits and measures their use of resources such as CPU, memory, and input/output.
Control Group
├── CPU Usage Limit
├── Memory Limit
├── Input/Output Priority
├── Process Count Limit
└── Resource-Usage Statistics
Linux kernel documentation describes cgroups as a structure that associates sets of tasks with resource parameters from multiple subsystems.
cgroup v2 organizes resource control and delegation around a single unified hierarchy. Kernel documentation explains that cgroup namespaces can be used as delegation boundaries.
Control groups reduce interference between services caused by resource exhaustion, but they do not perfectly isolate every hardware resource, including CPU time, memory bandwidth, caches, and disks. Performance interference may remain between workloads running on the same host.
Differences Between Containers and Virtual Machines
| Category | Container | Virtual Machine |
|---|---|---|
| Kernel | Shares the host kernel | Separate kernel for each guest |
| Startup | Generally fast | Requires guest boot |
| Resource Usage | Relatively low | Requires resources for a complete operating system |
| Operating-System Type | Must be compatible with the host kernel | Different guest operating systems are possible |
| Isolation Boundary | Based on processes and kernel functions | Based on the hypervisor and hardware |
| Primary Use | Application packaging and deployment | Full operating-system isolation and testing |
| Vulnerability Impact | Shares host-kernel vulnerabilities | Hypervisor vulnerabilities form the main boundary |
Containers do not run separate kernels, so they are lightweight and can start quickly. However, because every container shares the same host kernel, kernel vulnerabilities or excessive privilege settings can affect multiple containers and the host.
Virtual machines use a separate kernel for each guest and can therefore provide stronger isolation, but require more resources and have greater startup overhead.
Windows also distinguishes between process-isolated containers and Hyper-V-isolated containers. Microsoft explains that Hyper-V-isolated containers, enclosed in lightweight virtual machines, provide a stronger hardware-level security boundary than process-isolated containers.
Container Security
Using containers does not automatically make a program secure. Secure container execution requires settings such as the following:
- Running as a non-administrator user
- Removing unnecessary Linux capabilities
- Restricting access to host devices
- Using a read-only root file system
- Minimizing host-path mounts
- Restricting system calls
- Applying network policies
- Setting resource limits
- Verifying image signatures and sources
- Keeping the kernel and runtime updated
- Excluding secrets from images
Providing a container with the host's entire file system, devices, or container-runtime socket greatly weakens the meaning of isolation.
The root user inside a container does not always have identical privileges on the host. However, a container without user namespaces and with many granted capabilities may pose a greater risk to the host.
Process Isolation and Resource Isolation
Security isolation and resource isolation are related but distinct concepts.
Security Isolation
Prevent Access to Unauthorized Data and Functions
Resource Isolation
Prevent Excessive Use of CPU, Memory, and Input/Output
Even a process completely blocked from file access can interfere with other programs if it consumes CPU indefinitely. Conversely, a process with limited CPU usage may still read important files if permissions are misconfigured.
Sandboxes and containers must therefore combine access restrictions with limits on CPU, memory, process count, and input/output usage.
Linux device cgroups can restrict the opening or creation of device files for each group according to an allowlist.
Device Isolation
Because devices can perform direct memory access independently of the CPU, faulty or malicious devices and drivers must be prevented from reading or writing arbitrary memory.
An Input/Output Memory Management Unit can restrict the physical memory range accessible to a device through separate address-translation tables.
Device DMA Address
↓
IOMMU Translation
↓
Permitted Physical Memory Region
When a physical device is assigned directly to a virtual machine, an IOMMU can also prevent the device from accessing the memory of other virtual machines or the hypervisor.
Because device drivers often operate with high privileges between the kernel and hardware, they can become part of the attack surface. Methods include moving suitable devices to user-mode drivers, restricting driver memory access, and allowing only signed drivers.
Network Isolation
An operating system can provide separate network views to processes, containers, and virtual machines.
Network isolation can include the following elements:
- Virtual network interfaces
- Separate IP addresses and routing tables
- Firewall policies
- Network namespaces
- Port-access restrictions
- Virtual switches
- Network address translation
- Service-to-service communication policies
A container using a separate network namespace can have interfaces, addresses, and routing information different from those of the host and other containers. However, when virtual networks are connected, firewalls and service authentication are still required.
Network requests from another process or container should not be trusted merely because they originate on the same host. Local IPC and network communication may also require authentication and input validation.
Trusted Execution Environments
A Trusted Execution Environment is a structure that handles cryptographic keys, authentication information, and security operations in an execution area separated from the ordinary operating system.
Such an environment may provide the following functions:
- Isolated memory
- A separate privilege level
- Secure boot and measurement
- Protection of cryptographic keys
- Restricted access from the ordinary kernel
- Execution of security operations
Hardware security modules, TPMs, secure enclaves, and hypervisor-based secure regions can be used for these purposes.
A trusted execution environment should be kept as small as possible. As the amount of highly trusted code grows, the attack surface requiring verification also increases.
Limits of Isolation
Operating-system isolation allows multiple programs to share the same system safely, but it does not guarantee complete separation.
Factors that can weaken isolation boundaries include the following:
- Kernel and hypervisor vulnerabilities
- Incorrect access permissions
- Excessive administrator privileges
- Unsafe device drivers
- Shared memory and shared files
- Side channels involving CPU caches and execution timing
- Incorrect IPC input validation
- Excessive container capabilities
- Direct attachment of host paths and devices
- Exposed management interfaces
- Outdated operating systems and libraries
A Side-Channel Attack can infer information by observing execution time, caches, power consumption, or shared hardware state without directly reading protected memory. Logical isolation through address spaces and virtual machines therefore cannot block every flow of information.
Virtual machines and containers sharing the same physical CPU, caches, and memory bandwidth may still experience performance interference and some side-channel risks. Workloads requiring a high security level may use dedicated hardware and additional isolation policies.
Defense in Depth
Operating-system security combines multiple defensive mechanisms so that another layer can limit damage if one mechanism fails. This is called Defense in Depth.
Secure Boot
↓
Signed Kernel and Drivers
↓
Separation of User Mode and Kernel Mode
↓
Process Address-Space Isolation
↓
Users and Access Permissions
↓
Sandboxes and System Call Restrictions
↓
Virtualization and Containers
↓
Encryption and Auditing
↓
Updates and Vulnerability Response
For example, even if an application contains a vulnerability, a sandbox may restrict file access, user permissions may prevent system-setting changes, and address-space isolation may block access to another process's memory. Boundaries can be layered so that an attacker escaping a sandbox still requires a separate vulnerability to obtain kernel privileges.
Defense in depth does not mean adding every possible layer without consideration. Complex security settings can also be misconfigured, so the purpose and trusted subjects of each boundary must be clearly defined.
Trusted Computing Base
The Trusted Computing Base is the collection of hardware and software that must be trusted to enforce the system's security policy.
A trusted computing base can include the following elements:
- CPU and memory-protection features
- Firmware and bootloaders
- Hypervisors
- The operating-system kernel
- Security-policy managers
- Authentication services
- Privileged system services
- Cryptographic key-management components
In general, a trusted computing base is easier to verify when it is small and simple. Microkernel architectures that separate file systems, network services, and device drivers into user space may also aim to reduce the amount of code trusted inside the kernel.
However, if a user-space service has high privileges or is essential to enforcing security policy, it is also effectively part of the trusted computing base. The total scope of trust cannot be judged solely by the size of kernel code.
Summary
Operating-system security and isolation are fundamental conditions that allow multiple users and programs to share one computer. User mode and kernel mode separate ordinary programs from the operating-system core, while virtual address spaces isolate process memory. User accounts and access control restrict which subjects can use files, devices, processes, and system functions.
Sandboxes permit only the capabilities required by an application and reduce the scope of damage after compromise. Code signing and secure boot verify the source and integrity of executed code. Encryption, auditing, and update systems provide a foundation for protecting data, investigating incidents, and responding to newly discovered vulnerabilities.
Virtual machines separate different guest kernels through a hypervisor, while containers share the same host kernel and isolate processes and resources through namespaces, control groups, and privilege restrictions. Virtual machines generally provide a stronger kernel boundary, while containers offer lower resource usage and faster deployment.
No isolation mechanism guarantees complete security by itself. Vulnerabilities in kernels, hypervisors, drivers, and management services, as well as incorrect permissions and shared resources, can weaken protection boundaries. Operating systems therefore combine least privilege, access control, memory protection, sandboxing, virtualization, integrity verification, and continuous updates to establish multiple layers of trust boundaries.
Types and Families of Operating Systems
Operating systems can be classified into multiple types according to their purpose, execution environment, response-time requirements, number of users, hardware resources, and system architecture. A single operating system can have characteristics belonging to several types at the same time. For example, Linux-based operating systems can be used on personal computers, servers, smartphones, network equipment, and embedded systems, while QNX is both an embedded operating system and a real-time operating system.
An operating-system type is primarily classified according to its intended use and operational characteristics, while an operating-system family is distinguished according to a shared kernel, interfaces, code, and historical origin. Operating systems in the same family may be used for different purposes, while systems from different families may compete in the same markets and environments.
Types by Purpose and Environment
| Type | Main Characteristics | Representative Examples |
|---|---|---|
| General-Purpose Operating System | Supports diverse applications and devices and handles multiple kinds of use | Windows, macOS, Linux, FreeBSD |
| Server Operating System | Emphasizes network services, multiple users, remote administration, high availability, and large-scale resources | Linux, Windows Server, FreeBSD |
| Mobile Operating System | Centers on touch input, mobile communication, sensors, power management, application permissions, and sandboxing | Android, iOS, iPadOS |
| Embedded Operating System | Targets specific devices and constrained hardware resources, emphasizing a small footprint and device control | Zephyr, FreeRTOS, embedded Linux |
| Real-Time Operating System | Emphasizes predictability and the ability to complete tasks within defined time limits rather than merely processing them quickly | QNX, FreeRTOS, Zephyr, VxWorks |
| Mainframe Operating System | Emphasizes very large numbers of concurrent jobs and input/output operations, large-scale transactions, virtualization, and continuous availability | z/OS, z/VM, z/VSE |
| Distributed Operating System | Attempts to manage resources from multiple computers as a single integrated system | Plan 9, Amoeba, experimental distributed operating systems |
A general-purpose operating system runs different kinds of applications, including document editing, web browsing, software development, games, media, and business software, within the same environment. It generally provides a graphical user interface, file systems, networking, user accounts, multitasking, and broad device support.
A server operating system focuses more on reliably processing requests from multiple users and providing network services than on interactive personal use. It runs web servers, databases, file servers, directory services, virtual machines, and containers for extended periods, making remote administration, automation, resource limits, and failure recovery important. Microsoft describes Windows Server as an enterprise server platform for running applications, services, and workloads across on-premises, hybrid, and cloud environments.
A mobile operating system manages the limited battery capacity, mobile and wireless connections, cameras and location sensors, and touch-based user interfaces of smartphones and tablets. Applications are commonly isolated in separate processes and sandboxes, while sensitive resources such as cameras, microphones, contacts, and location information are made available only to applications that have received permission. Android is based on a Linux LTS kernel combined with Android-specific changes and uses Linux kernel security, inter-process communication, and application sandboxing at the operating-system level.
An embedded operating system is incorporated into devices with specific purposes, such as automotive control units, sensors, home appliances, network equipment, wearable devices, and industrial controllers. It may need to operate with less memory and storage than a general-purpose operating system and may omit some features such as displays, file systems, or dynamic process creation. Zephyr provides a small kernel for resource-constrained sensors, controllers, smartwatches, and Internet of Things devices.
A Real-Time Operating System emphasizes determinism and predictability—the ability to start or complete a task within a defined time even under worst-case conditions—rather than average processing speed. It may provide rapid preemption of high-priority tasks, precise timers, priority-inversion prevention, bounded latency, and predictable memory-management functions. FreeRTOS is a small real-time kernel for microcontrollers and small processors, while QNX provides a POSIX-based real-time operating-system environment for embedded systems.
A real-time system does not necessarily execute every task quickly at all times. Less important tasks may run later, but tasks with timing constraints must be processed within the required time according to defined priorities and scheduling rules. Real-time operating systems can be used in automobiles, robotics, aerospace and railway equipment, industrial control, medical devices, and communication equipment.
A mainframe operating system targets environments that continuously process very large numbers of concurrent users, batch jobs, transactions, and input/output operations. IBM describes z/OS as a mainframe application environment for workloads requiring reliability, security, and continuous availability and explains that it has developed to process thousands of programs and users concurrently.
Batch Operating Systems and Time-Sharing Operating Systems are important historical classifications, but in modern operating systems they remain more as execution modes provided together than as completely separate product categories. A modern server operating system can process interactive users and network services while simultaneously running scheduled batch jobs.
The term Network Operating System was also historically used as a separate classification for server-centered operating systems that managed network files, printers, and user accounts. Today, most general-purpose operating systems provide TCP/IP, remote administration, file sharing, and authentication as standard functions, so the boundary of this independent category has weakened.
A distributed operating system attempts to present the processors, memory, files, and devices of multiple networked computers as a single operating-system environment. Modern large-scale distributed services are more commonly constructed by placing cluster managers, distributed storage systems, and container orchestration platforms on top of individual operating systems such as Linux or Windows Server rather than using a single distributed operating system.
Major Operating-System Families
UNIX and Unix-Like Systems
UNIX does not simply refer to every operating system with similar command-line tools and file-system structures. The UNIX trademark is managed by The Open Group, and only systems that satisfy the requirements of the Single UNIX Specification and receive certification may officially use the UNIX trademark. This specification defines operating-system interfaces, shells, and common utilities, and its core portions are connected to the POSIX standards.
A Unix-Like Operating System refers broadly to an operating system influenced by UNIX processes, files, permissions, shells, and system interfaces, regardless of whether it has official UNIX certification. Linux and BSD operating systems are generally classified as Unix-like, but not every individual distribution or system has received UNIX certification.
Common characteristics of Unix-like systems include hierarchical file systems, multi-user operation, process-based execution, file descriptors, shells, small command-line tools, and the composition of programs through pipes. POSIX defines common interfaces for this environment and improves source-code portability among different operating systems.
BSD Family
BSD is a family of operating systems and software developed from UNIX at the University of California, Berkeley. Major modern BSD operating systems include FreeBSD, OpenBSD, and NetBSD.
FreeBSD develops the kernel, base user space, system tools, and documentation together as a single operating-system project. Unlike a Linux distribution, which combines the Linux kernel with user-space components from multiple independent projects, FreeBSD manages its base system as one integrated project. FreeBSD's official documentation separately describes the history of FreeBSD, its relationship with other operating systems, and the project's development model.
Networking technologies, file systems, and system interfaces developed in BSD influenced many other operating systems. Apple's Darwin and XNU also include technologies from FreeBSD and other BSD systems. Apple describes XNU as a hybrid kernel combining the Mach kernel, FreeBSD components, and I/O Kit.
Linux Family
Linux refers primarily to the kernel at the core of an operating system rather than to a single complete operating-system product. An actual user environment is constructed by combining the Linux kernel with system libraries, shells, initialization systems, package managers, graphical environments, and applications. Such a complete system is called a Linux Distribution.
Representative Linux distributions include Debian, Ubuntu, Fedora, Red Hat Enterprise Linux, SUSE Linux Enterprise, and Arch Linux. Although distributions use the same Linux kernel family, they differ in package formats, update policies, default tools, support periods, target users, and system configuration.
The Linux kernel is used not only for servers and personal computers, but also as the foundation of supercomputers, network equipment, embedded devices, and smartphones. Official Linux kernel documentation covers user-space APIs, file systems, memory management, drivers, administration, and multiple architectures.
Android uses the Linux kernel but does not provide the same user space and application environment as a typical desktop Linux distribution. Android is a separate operating-system platform that combines the Android Common Kernel with hardware abstractions, native libraries, the Android Runtime, system services, and an application framework.
Windows NT Family
Windows NT is an operating-system family developed by Microsoft and forms the architectural foundation of modern Windows client and Windows Server products. Windows separates user-mode and kernel-mode components and provides systems for processes, virtual memory, object management, input/output management, security reference monitoring, and device drivers.
Windows 95, Windows 98, and Windows Me inherited the foundation of the MS-DOS family, but consumer versions of Windows were unified with the NT family beginning with Windows XP. Current Windows and Windows Server products differ in purpose, included functions, and support policies, but are based on a shared Windows kernel architecture and common system components.
Windows client systems target personal computers and workstations, while Windows Server targets file and web services, directories, virtualization, remote desktops, and enterprise infrastructure. Windows Server can provide installations that include a graphical environment as well as Server Core installations containing a smaller set of components.
Darwin and the Apple Operating-System Family
Darwin is the open foundational system that forms the core of Apple's operating systems. Darwin's XNU kernel combines Mach, BSD-family components, and I/O Kit and is used by macOS and iOS.
The Apple operating-system family includes macOS, iOS, iPadOS, watchOS, tvOS, and visionOS. Although they differ in devices, user interfaces, and application-execution policies, they share the kernel, file systems, secure boot, code signing, and multiple system technologies. Apple provides portions of the open-source code for its operating systems and development tools by release, including macOS and iOS releases.
macOS is a general-purpose desktop operating system that provides both a UNIX environment and a graphical application ecosystem. iOS, iPadOS, and related systems target mobile and specialized-device environments and use stronger application isolation and more restricted distribution and permission models.
Mainframe Families
The IBM mainframe environment includes different operating systems such as z/OS, z/VM, and z/VSE.
- z/OS targets environments requiring large-scale transaction and batch processing, many concurrent users, and high availability.
- z/VM acts as both a control program and a hypervisor that creates multiple virtual machines and runs other operating systems.
- z/VSE supports traditional batch and transaction-processing workloads with a relatively smaller configuration.
IBM describes z/OS as its primary mainframe operating system for continuous availability and large-scale workload processing, while describing z/VM as a virtualized operating environment that runs other operating systems inside virtual machines.
Alongside traditional mainframe workloads, z/OS also includes the z/OS UNIX System Services environment, which provides POSIX APIs and a shell. This allows traditional mainframe programs and Unix-like applications to be used together within one operating system.
Real-Time Operating-System Families
Real-time operating systems are not a single family descended from one common ancestor, but a classification encompassing multiple independent operating systems and kernels developed to satisfy real-time constraints.
QNX is a POSIX-family real-time operating system centered on a microkernel and message passing. It provides processes, threads, timers, interrupts, and resource managers so that it can scale from small embedded devices to complex distributed and control systems.
FreeRTOS is a real-time kernel for microcontrollers and small processors, primarily providing task scheduling, queues, timers, and synchronization functions. It is closer to a small kernel embedded within an application than to a complete desktop operating system.
Zephyr is an open operating-system project that combines a small real-time kernel with device drivers, networking, file systems, security, and multiple embedded services. It supports various processor architectures and resource-constrained embedded devices.
Fields of Use
Operating systems are used in nearly every general-purpose computer and electronic device that runs programs. However, the required user interfaces, device support, response times, security mechanisms, and resource-management policies differ according to the purpose of the system.
Personal Computers and Work Environments
Personal computer operating systems provide an environment in which graphical user interfaces, file management, web browsers, media applications, games, document-editing software, and development tools can run together. Representative examples include Windows, macOS, and desktop Linux Distributions.
The following elements are important in this environment:
- Broad hardware and peripheral-device support
- Graphical user interfaces
- User accounts and file protection
- Application installation and updates
- Power saving and battery management
- Audio, video, and graphics acceleration
- Accessibility and internationalization
- Compatibility with existing applications
Although a personal computer is generally centered on one user, multiple user accounts, system services, and background processes operate concurrently within the operating system.
Servers and Cloud Computing
Server operating systems run web services, databases, file sharing, authentication, email, virtual machines, and containers for extended periods. Remote administration, automation, multi-user operation, high network throughput, and failure recovery are important.
In cloud environments, multiple layers are combined, including the host operating system and hypervisor on a physical server, the guest operating system inside a virtual machine, and the host kernel used by containers.
Physical Server
↓
Host Operating System or Hypervisor
↓
Virtual Machine
↓
Guest Operating System
↓
Containers and Applications
Major cloud platforms provide operating-system images including Linux and Windows Server. Google Compute Engine provides preconfigured images for Linux and Windows operating systems, while AWS Systems Manager supports Linux and Windows Server as managed operating systems.
Because servers may not require a display or local input devices, they can be installed without a graphical user environment and use only command-line tools and remote administration services. Reducing unnecessary components can decrease storage and memory usage, the number of components requiring updates, and the attack surface.
Smartphones and Personal Devices
Smartphone and tablet operating systems manage telephone calls, messaging, cameras, location information, and mobile communication and require user permission when applications attempt to use sensitive device functions.
The following elements are important in mobile environments:
- Battery and thermal management
- Touch and gesture input
- Cellular and wireless networking
- Cameras, microphones, and location sensors
- Application sandboxing
- Restrictions on background execution
- Application signing and distribution
- Device encryption
- Rapid sleep and resume
Android is an open foundational platform that can be used by multiple manufacturers and hardware systems, while iOS and iPadOS provide environments in which Apple hardware and software are integrated. Both families strongly separate application processes, user data, and device permissions. Android's official documentation explains that Linux kernel security and application sandboxing restrict the behavior of applications, including those containing native code.
Embedded Devices and the Internet of Things
Embedded operating systems perform specific functions inside sensors, home appliances, routers, cameras, wearable devices, drones, and industrial equipment.
The following conditions may be important in this environment:
- Very limited memory and storage
- Low power consumption
- Fast booting
- Long-term uninterrupted operation
- Control of hardware registers and interrupts
- Remote updates
- Restricted network connectivity
- Security against physical access
- Safe recovery after failures
Small real-time operating systems such as FreeRTOS and Zephyr can be used on small microcontrollers, while embedded Linux and Android-based systems can be used on more capable devices. FreeRTOS targets microcontrollers and small processors, while Zephyr targets systems ranging from sensors to complex embedded controllers and Internet of Things devices.
Automobiles and Industrial Control
In automobiles, factory equipment, robots, and medical devices, programs directly control physical machinery. Because incorrect commands or long delays can result in equipment damage and safety problems, real-time behavior, reliability, and fault isolation are important.
Operating systems in this environment may provide the following functions:
- Priority-based preemptive scheduling
- Predictable interrupt latency
- Memory protection between tasks
- Restarting services after failures
- Watchdog timers
- Secure communication
- Redundancy and failure detection
- Development support for certification and safety standards
QNX provides real-time operating systems and hypervisors for embedded environments including automotive, industrial, and control systems, while FreeRTOS and Zephyr can also be used in various small control devices.
Networking and Communication Equipment
Routers, switches, firewalls, wireless base stations, and storage devices must process large numbers of packets and input/output requests with low latency.
Operating systems for network equipment emphasize the following:
- High packet-processing throughput
- Support for network interfaces and accelerators
- Remote configuration and administration
- Updates without service interruption
- Separation of user and management domains
- Routing and firewall policies
- Isolation among multiple control processes
- Hardware redundancy
Linux and BSD-family systems can be used in networking equipment because of their mature TCP/IP network stacks and device drivers, while QNX and specialized operating systems may be used in communication equipment with real-time constraints.
Mainframes and Large-Scale Transactions
Mainframe operating systems process critical transactions and batch workloads for banks, insurance companies, airline reservation systems, governments, and large enterprises. Supporting very large amounts of input/output and many concurrent users while avoiding prolonged service interruption is important.
z/OS provides an environment that manages large virtual and physical storage spaces and input/output workloads while processing thousands of programs and users together.
A mainframe environment can configure multiple logical partitions and virtual machines within one physical system to isolate different operating systems and workloads. Batch processing, online transactions, databases, and UNIX applications may also run together within a single system.
High-Performance Computing and Research
Supercomputers and computing clusters use thousands or more processors and accelerators, high-speed networks, and distributed storage to perform scientific computation, weather forecasting, physical simulations, and artificial intelligence training.
The following elements are important in this environment:
- Support for massively parallel processors
- NUMA memory management
- GPUs and computing accelerators
- High-speed networking and remote direct memory access
- Large-scale file systems
- Batch job schedulers
- Recovery of failed nodes
- Performance measurement and resource allocation
TOP500 records the operating systems and operating-system families of high-performance computers as separate classification fields, and many systems in the current list use Linux-family operating systems such as Ubuntu and Red Hat Enterprise Linux.
The operating system alone does not manage the entire cluster. Job schedulers, message-passing libraries, distributed file systems, and cluster-management tools are added on top of it.
Game Consoles and Specialized Devices
Game consoles, set-top boxes, smart televisions, virtual-reality devices, and kiosks use hardware similar to general-purpose computers but provide specialized user experiences, security models, and distribution systems.
Operating systems in this environment may emphasize the following:
- Low-latency graphics and audio
- Optimization for limited hardware configurations
- Isolation of applications and games
- Code signing and integrity verification
- Power saving and rapid resume from standby
- Controllers and sensors
- Content protection
- Centralized updates
Some specialized devices are based on existing operating-system families such as BSD, Linux, or Windows while modifying the user interface, security policies, and development APIs for the device's intended purpose.
Software Development and Testing
An operating system is both the execution target of applications and the foundation of software-development tools. Compilers, debuggers, build systems, emulators, and profilers use operating-system interfaces for processes, files, memory, and debugging.
Developers can use the following features to test multiple operating systems and versions:
- Virtual machines
- Containers
- Operating-system emulators
- Compatibility layers
- Cross-compilation
- Remote device debugging
- System call tracing
- Kernel and performance profiling
Virtual machines are suitable for testing a different kernel and a complete operating-system environment, while containers are suitable for isolating an application's user space and dependencies on the same kernel.
Market Share
Operating system market share produces different results depending on what is being measured. When measured by web usage on personal computers, Windows is the most widely used, while Android accounts for the largest share of total web usage when smartphones are included. Linux and other UNIX-like operating systems dominate web servers and supercomputers, while MINIX 3 and various embedded Secure OSes are added when management processors and security processors inside computers are also counted as operating systems.
Operating system market share is therefore not a single figure dividing one global market. Even within the same computer, the host operating system directly used by the user, an operating system for hardware management, and real-time operating systems in device firmware may all run simultaneously.
One personal computer
User domain
└── Windows, Linux, or macOS
Intel management domain
└── MINIX 3–based operating system in Intel ME
AMD management domain
└── Secure OS in AMD Secure Processor
Peripheral devices
├── Storage controller firmware
├── Network device firmware
└── Embedded operating environments for power and system management
Criteria for Market Share Statistics
Commonly published operating system market share figures are not based on a complete census of the operating systems installed on computers. They are calculated by analyzing the user agents and page views of devices accessing websites or by aggregating the number of devices shipped by manufacturers and the number of active users.
StatCounter Global Stats analyzes more than 3 billion page views generated each month across more than 1 million websites worldwide. It identifies the browser, operating system, screen resolution, and device type for each page view and uses this data to calculate operating system usage shares.[14]
This method reflects actual web usage environments, but the following devices rarely appear in the statistics:
- Servers that do not run web browsers
- Industrial equipment that is not directly connected to the Internet
- Embedded operating systems in automobiles and home appliances
- Control processors in storage and network devices
- Operating systems inside virtual machines and containers that do not access the web
- Internal hardware operating environments such as Intel ME and AMD Secure Processor
Web usage share is useful for measuring the influence of operating systems directly used by users, but it does not represent the number of installations of every operating system running worldwide.
Desktop Operating Systems
In StatCounter’s worldwide desktop web usage statistics for June 2026, Windows held the largest share at 56.61%. OS X accounted for 11.89%, macOS for 4.48%, Linux for 4.36%, and Chrome OS for 1.21%, while 21.45% of page views came from operating systems that could not be identified.[15]
| Desktop operating system | Worldwide web usage share in June 2026 |
|---|---|
| Windows | 56.61% |
| Unidentified | 21.45% |
| OS X | 11.89% |
| macOS | 4.48% |
| Linux | 4.36% |
| Chrome OS | 1.21% |
StatCounter counts Apple operating systems under separate OS X and macOS categories. When the two categories are combined into a single macOS family, their total share is 16.37%. When unidentified operating systems are excluded and the shares are recalculated using only known operating systems, Windows accounts for approximately 72.1%.
Windows share among identified operating systems
56.61
──────────── × 100
100 - 21.45
= approximately 72.1%
The common understanding in the general public and software market that Windows is the world’s leading desktop operating system is therefore valid. However, 56.61% is not the percentage of all PCs owned worldwide, but the percentage of desktop web page views observed in June 2026.
Linux is not a single complete product but a common kernel used by numerous Linux distributions and specialized operating environments. Desktop statistics therefore combine the usage of Ubuntu, Fedora, Arch Linux, and other distributions under the Linux category. By contrast, Apple operating systems are displayed separately as OS X and macOS depending on how they are identified in the statistics.
Mobile Operating Systems
In worldwide mobile web usage in June 2026, Android accounted for 69.14% and iOS for 30.79%. The two operating systems together constituted more than 99.9% of all mobile web usage, and the modern smartphone operating system market has effectively formed a two-platform structure dominated by Android and iOS.[16]
| Mobile operating system | Worldwide web usage share in June 2026 |
|---|---|
| Android | 69.14% |
| iOS | 30.79% |
| Unidentified | 0.03% |
| Linux | 0.01% |
| KaiOS | 0.01% |
| Windows | 0.01% |
Android uses the Linux kernel, but general market share statistics classify it as an independent Android operating system. Android’s share is therefore not directly added to the desktop Linux share. When analyzed by kernel family, Android, Chrome OS, and various embedded systems may be included in the Linux family, but when classified by user-facing operating system product, each is a separate platform.
Operating Systems Across All User Devices
Across worldwide web usage including desktops, mobile devices, and tablets in June 2026, Android held the largest share at 36.21%, followed by Windows at 26.67% and iOS at 16.62%. OS X accounted for 5.60%, macOS for 2.11%, and unidentified operating systems for 10.12%.[17]
| Operating system | Total worldwide web usage share in June 2026 |
|---|---|
| Android | 36.21% |
| Windows | 26.67% |
| iOS | 16.62% |
| Unidentified | 10.12% |
| OS X | 5.60% |
| macOS | 2.11% |
In these statistics, Android is the world’s most widely used user-facing operating system. Windows ranks first on desktops, but when all web-using devices, including smartphones, are combined, its share is lower than Android’s.
The expression “the world’s most widely used operating system” must therefore be qualified by scope as follows:
- Windows ranks first in worldwide desktop web usage.
- Android ranks first in worldwide mobile web usage.
- Android also ranks first in total web usage across desktop and mobile devices.
- MINIX 3 ranks first in cumulative installed base when hardware-embedded operating systems in x86 computers are included.
Server Operating Systems
Worldwide server operating system market share is more difficult to measure accurately than desktop and mobile market share. Many servers run in private networks, internal corporate environments, and cloud data centers without disclosing operating system information externally. Because multiple virtual machines and containers may run on a single physical server, the number of physical devices and the number of operating system instances also do not correspond directly.
According to W3Techs statistics, which analyze the server operating systems of public websites, 91.7% of websites whose operating systems could be identified used UNIX-like operating systems in June 2026. This figure is based not on every server worldwide, but on websites whose technology configurations can be identified externally.[18]
The high share of UNIX-like systems on servers results from the widespread use of Linux, BSD, and commercial UNIX systems in web servers, databases, and cloud infrastructure. Windows Server also holds an important position in enterprise directories, file servers, business applications, and the Microsoft ecosystem.
Server market share varies depending on the following criteria:
- Number of physical servers shipped
- Number of virtual machine instances
- Number of operating system images running in the cloud
- Number of public websites
- Volume of web requests processed
- Number of internal corporate servers
- Number of container hosts
The operating system share of public websites should therefore not be interpreted as the total number of server installations.
Supercomputers
In high-performance computing, Linux-based operating systems are used as the de facto standard. Modern supercomputers listed in the TOP500 are primarily built around Red Hat Enterprise Linux, Ubuntu, SUSE-based systems, and manufacturer-specific modified Linux environments. The June 2026 TOP500 list also includes systems identified as running RHEL, Ubuntu, and generic Linux.[19]
The widespread use of Linux in supercomputers is attributable to the following factors:
- The kernel and user space can be modified for the system’s intended purpose
- Support for diverse CPU and accelerator architectures
- Support for large-scale NUMA systems and parallel processing
- Support for high-speed networks and distributed file systems
- Unnecessary graphical and desktop components can be removed
- An open structure that allows research institutions and manufacturers to develop the system jointly
This market share indicates which operating system families are used by the world’s highest-performance computing systems, regardless of the number of ordinary users.
Market Share by Kernel Family
When operating systems are grouped by kernel and historical lineage rather than by operating system product, the shape of market share changes.
Android and Chrome OS use the Linux kernel, and many servers, supercomputers, network devices, and embedded systems are also based on Linux. The Linux kernel family is therefore deployed across a much broader range of environments than its desktop market share suggests.
macOS, iOS, iPadOS, watchOS, tvOS, and visionOS share the XNU kernel and Darwin foundation. When grouped as a single Apple operating system family, desktop macOS and mobile iOS belong to the same technological lineage.
The UNIX family encompasses Linux, BSD, macOS and iOS, various commercial UNIX systems, and some real-time operating systems. Regardless of formal UNIX certification, operating systems influenced by UNIX concepts involving processes, files, permissions, shells, and POSIX interfaces occupy a large part of modern server, mobile, desktop, and embedded environments.
| Classification criterion | Examples counted differently |
|---|---|
| Operating system product | Android, Ubuntu, and macOS are counted separately |
| Kernel | Android and Ubuntu are combined into the Linux family |
| Platform ecosystem | macOS and iOS are combined as Apple operating systems |
| Historical lineage | Linux, BSD, and macOS are classified as UNIX-like systems |
| User interface | Only host operating systems directly operated by users are counted |
| Running instance | Host operating systems and embedded operating systems are each counted independently |
The fact that Linux has a low desktop market share therefore does not contradict the fact that the Linux kernel is used across the widest variety of computers in the world.
Operating Systems Inside Hardware
Operating systems are not limited to user-facing software that provides screens, windows, and application launchers. When an operating system is defined as software that manages hardware resources and provides common services to other programs, the operating environments of management processors and security processors included in CPUs and chipsets also qualify as operating systems.
Intel used a modified version of MINIX 3 in Intel Management Engine 11, which was introduced with the Skylake generation. Intel ME runs on a management processor separate from the main x86 processor and starts services required for system initialization, management, and security before the host operating system.
MINIX creator Andrew Tanenbaum explained that Intel used MINIX in ME 11 and that ME 11 was installed in nearly every modern desktop and laptop computer in the world at the time. As a result, MINIX 3 became an operating system installed on more x86 computers than Windows, Linux, or macOS.[20]
This does not mean that users choose between Windows and MINIX. On Intel-based computers, MINIX 3 runs on the Intel ME management processor while Windows, Linux, or macOS runs on the main processor.
Intel-based personal computer
Main x86 processor
└── Windows, Linux, or macOS
Intel Management Engine
└── MINIX 3–based management operating system
The two operating systems therefore do not compete for shares of the same market but are installed together at different system layers. General desktop statistics record only the host operating system on which the user runs a web browser, so MINIX 3 in Intel ME is not included.
Installed Base of MINIX 3
MINIX 3 is the most widely deployed single operating system by cumulative installed base across x86 personal computers when hardware-embedded operating systems are included. Intel systems equipped with ME 11 included a MINIX 3–based management environment regardless of the host operating system installed by the manufacturer or user.
Windows market share indicates which desktop operating systems users accessed the web with at the same point in time. The installed base of MINIX 3 indicates how widely hardware containing Intel ME 11 was deployed.
| Criterion | Windows | MINIX 3 |
|---|---|---|
| Execution location | Main x86 processor | Intel management processor |
| User interface | Provided | Not provided to ordinary users |
| General web statistics | Included | Not included |
| Installation method | Installed by manufacturers or users | Embedded in Intel platform firmware |
| Primary role | Running user applications | Hardware management and security services |
| Measurement basis | Web usage and active devices | Installed base of hardware equipped with ME 11 |
Windows is therefore the leading desktop operating system by user market share, while MINIX 3 has the largest installed base across x86 personal computers when operating systems inside hardware are included. Each statistic is valid for a different system layer and measurement criterion.
AMD Secure Processor
AMD processors integrate an AMD Secure Processor that operates separately from the main x86 cores. AMD Secure Processor performs functions such as boot verification, firmware trust establishment, cryptography, and fTPM on a dedicated security processor. AMD describes AMD Secure Processor 2.0 in modern AMD PRO platforms as a dedicated security processor that verifies code before execution and establishes a hardware root of trust.[21]
The AMD PSP firmware architecture includes PSP SecureOS firmware as a separate component. SecureOS initializes the internal operating system structure, runs fTPM as a trusted application, configures interfaces between the CPU and BIOS, and enters a continuously running state in which it waits for commands.[22]
AMD-based personal computer
Main x86 processor
└── Windows or Linux
AMD Secure Processor
└── PSP SecureOS
├── Secure boot
├── Firmware verification
├── fTPM
└── Secure applications
AMD SecureOS also does not appear in desktop or mobile web usage statistics. A single AMD-based computer runs both a user-facing operating system and an operating system for hardware security.
Scale of Embedded Operating Systems
Modern computers and electronic devices contain numerous operating environments that users do not directly recognize.
- Storage controllers in SSDs and HDDs
- Network interfaces and wireless communication chips
- Keyboards, mice, and input devices
- Displays and graphics devices
- Power management controllers
- Baseboard management controllers in servers
- Electronic control units in automobiles
- Cameras and sensors
- Smart appliances and Internet of Things devices
These devices run bare-metal firmware, small schedulers, RTOSes, or complete embedded operating systems. Even a single laptop may contain several independent firmware execution environments in addition to the operating system selected by the user.
The total number of operating systems running worldwide therefore cannot be treated as equal to the number of devices. A smartphone and a personal computer do not each run only one operating system. Beneath the main operating system, multiple auxiliary processors and controllers may simultaneously run independent operating environments.
User Market Share and Total Installed Base
Operating system market share can broadly be divided into two perspectives.
User Market Share
This perspective concerns host operating systems through which users directly run applications and interact with files and screens.
Desktop
Windows ranks first
Mobile
Android ranks first
All user devices
Android ranks first
Total Installed Base
This perspective includes not only host operating systems but also operating system instances in management processors, security processors, embedded devices, and virtual machines.
One computer
├── Host operating system
├── Management engine operating system
├── Security processor operating system
├── Storage device firmware
└── Network and power management environments
User market share is suitable for analyzing operating system ecosystems, application markets, and user experience. Total installed base shows how many operating system layers actually constitute modern computers.
The two statistics do not replace each other. Windows may dominate the desktop user market while MINIX 3 runs alongside it inside the same Intel computer, and Android may dominate mobile usage while internally operating together with the Linux kernel and multiple device firmware environments.
Interpreting the Statistics
The following factors must be presented when explaining operating system market share:
- Type of device measured
- Whether it is a user-facing or embedded operating system
- Whether the metric represents web usage or installations
- Whether it measures active devices or cumulative shipments
- Whether it classifies operating system products or kernel families
- Whether it counts physical devices or virtual instances
- Date and region of the survey
The statement “Windows is the world’s leading operating system” is correct for the desktop user market, but it does not include mobile devices, servers, supercomputers, or embedded systems. The statement “Android is the world’s leading operating system” is correct for combined desktop and mobile web usage, but it does not include servers and embedded devices that do not access the web.
When the technical definition of an operating system is applied across the entire computer hierarchy, the operating systems visible to users and the operating systems actually running on hardware cover different scopes. Windows dominates the desktop user market, while Android dominates web usage across all user devices. Linux and UNIX-like systems are central to servers and supercomputers, and MINIX 3 forms the broadest installed base when hardware-embedded operating systems in x86 personal computers are included.
Operating system market share should therefore be understood not as a single ranking table, but as a set of statistics representing the distribution of the multiple layers that constitute modern computing.
Related Articles
- Kernel
- System Call
- Process
- Thread
- CPU Scheduling
- Virtual Memory
- File System
- Device Driver
- Input/Output
- Interrupt
- Inter-Process Communication
- Synchronization
- Access Control
- User Mode
- Kernel Mode
- Sandbox
- Virtualization
- Hypervisor
- Virtual Machine
- Container
- Real-Time Operating System
- Embedded Operating System
- Server Operating System
- Mobile Operating System
- Distributed Operating System
- UNIX
- POSIX
- BSD
- Linux
- Linux Distribution
- Windows NT
- Darwin
- Android
- iOS
- FreeBSD
- QNX
- FreeRTOS
- Zephyr
- z/OS
- learn.microsoft.com ↩
- learn.microsoft.com ↩
- developer.apple.com ↩
- developer.apple.com ↩
- learn.microsoft.com ↩
- man7.org ↩
- man7.org ↩
- developer.apple.com ↩
- docs.kernel.org ↩
- learn.microsoft.com ↩
- learn.microsoft.com ↩
- developer.apple.com ↩
- man7.org ↩
- StatCounter Global Stats FAQ ↩
- Desktop Operating System Market Share Worldwide ↩
- Mobile Operating System Market Share Worldwide ↩
- Operating System Market Share Worldwide ↩
- Usage Statistics and Market Share of Operating Systems for Websites ↩
- TOP500 List – June 2026 ↩
- An Open Letter to Intel ↩
- AMD PRO Technologies Security White Paper ↩
- AMD Platform Security Processor Firmware Integration Guide ↩