Post

What the Operating System Provides

What the Operating System Provides

Stage 2 : Linux and Operating System Internals
Subject area 2.1 : The Operating System Model
Article 1

The short version

An operating system is the software layer that runs the hardware and gives programs safe ways to use it. Think of it as a manager and a guard. It splits the hardware between running programs, keeps them apart so they do not step on each other, and sets limits on what each one can do.

It decides how programs share CPU time, how memory is laid out and protected, how files and devices are reached, how network traffic is handled, and which actions each program may take. The OS does not make the hardware endless. It makes it usable, separate, and rule-bound.

Most backend code does not talk to hardware on its own. When a Go program calls net.Listen, a Java program opens a FileInputStream, or you run ps, each one asks the OS through a library to do the work: start a process, open a file, or move packets. The OS checks the request, schedules it, and later takes the resources back. For a backend service, much of the delay is simply the time spent waiting for the OS to hand over one of those resources, such as accepting a socket or reading a file from the page cache.

Where this article fits

This article is the overview for Subject 2.1: The Operating System Model, the map you read before the deep dives.

Prerequisites: Stage 1: Systems Programming Foundations (resources, ownership, failure).
Next: System Calls: How Programs Request Kernel Services, the controlled gate into the kernel. After that come Processes, Signals, Virtual Filesystems, Clocks, Scheduling, and Limits.

Later articles look at processes, signals, scheduling, memory mappings, filesystems, devices, and Linux resource limits. This article gives the full model so a backend engineer can tell which OS service a slow request is waiting on.

The operating system sits between programs and hardware

A computer holds hardware that can run instructions, store bits, move data, and talk to devices. Hardware by itself does not know how to run many separate programs safely.

The operating system supplies the rules and the interfaces that make that possible.

User space is the part of the system where ordinary programs run. Kernel space is the privileged part where the operating-system kernel runs. This is not about where files live. It is a wall that the processor and the operating system use to keep programs apart.

An application normally cannot run privileged instructions, change another process’s page tables, or drive a device on its own. It must ask for those operations through an operating-system interface. The kernel checks the request, does the work if allowed, and returns a result or an error.

Why programs need an operating system

Without an operating system, a program could in theory drive the hardware directly. That works for a small embedded program with one job, but it gets hard when several programs must share one machine.

The operating system solves several problems at once:

  • It gives each program a safe place to run.
  • It shares the CPU between pieces of work that can run.
  • It maps memory and keeps it apart.
  • It gives common ways to reach storage and devices.
  • It moves network data between programs and the network.
  • It checks permissions and keeps trust levels separate.
  • It tracks resources and sets limits on them.
  • It handles hardware events and interrupts.
  • It gives programs ways to talk to each other.

The operating system is therefore both a resource manager and a guard. The two jobs are tied together. To share a resource safely, you must control who can reach it and how much they can use.

The main services of an operating system

The exact design differs between Linux, Windows, macOS, and other systems, but the big jobs are much the same.

These jobs are not separate. A network socket is tracked through state that looks like a file descriptor. A process has a virtual address space. Reading a file may use memory for caching and CPU time for copying the data. Security checks can affect access to files, processes, devices, and network operations.

Process management

A process is a running program plus the state and resources it holds while running. The program is the code and data stored in a file on disk. The process is the running copy of that program that the operating system manages.

The operating system gives a process:

  • An address space
  • One or more threads of execution
  • Open file and socket references
  • Environment variables and arguments
  • Identity and permissions
  • Resource limits
  • Signal state
  • Scheduling state

Two processes can run the same program but differ in their arguments, environment variables, open files, memory contents, and permissions.

The operating system creates, schedules, pauses, resumes, and ends processes. It also gives processes ways to talk to each other, and it lets a parent process see when a child process exits.

A process is an important wall between programs, but it is not the smallest unit of execution. Threads inside one process share most of that process’s memory and resources. The process and thread articles will pull those two ideas apart carefully.

CPU management and scheduling

The CPU can only do a limited amount of work at once. The operating system scheduler picks which runnable thread should run on which processor.

When a thread waits for a file, a network operation, a lock, or a timer, it may not need CPU time. The scheduler can run a different thread instead. When the operation is ready, the waiting thread can run again.

Scheduling is not only about being fair. It changes latency, throughput, priorities, CPU affinity, cache locality, and behavior under overload. A process may have enough total CPU capacity yet still stall because its threads wait behind other work or fight for a lock.

Later articles explain context switches, scheduling policies, priorities, affinity, and the cost of too much concurrency.

Memory management

The operating system gives each process a virtual address space. A virtual address is an address that a process uses. The operating system and the hardware turn it into a real memory location, or they note that the page is not there right now.

This makes a process feel like it owns a big, private memory space even though the real memory is shared.

The operating system protects memory so that one process normally cannot read or write another process’s memory. It also marks regions as readable, writable, or executable, and it handles page faults when a process touches a page that needs attention.

Memory management is more than handing out bytes. It includes:

  • Creating and destroying address spaces
  • Mapping code, data, stacks, heaps, and shared libraries
  • Enforcing page permissions
  • Sharing pages when safe
  • Reclaiming memory under pressure
  • Handling page faults
  • Accounting for memory usage
  • Protecting the kernel from user programs

Virtual memory, page tables, address translation, and page faults get their own deep articles because they are core systems ideas.

Files, filesystems, and storage

The operating system gives programs a file interface so they can store and read data without managing the physical layout of every storage device.

A file is a named object that holds data and metadata. A filesystem organizes files, directories, permissions, timestamps, and how storage is used. The operating system follows a path, checks access, finds the right filesystem objects, and moves data through the page cache or the storage device.

The file idea hides the physical details, but storage latency, caching, durability, permissions, and filesystem behavior can still affect the program.

The operating system also shows devices through drivers and interfaces. A device driver turns general operating-system operations into commands that a specific device understands. Drivers may handle interrupts, DMA, queues, and errors that are unique to that device.

Networking

The operating system provides networking interfaces so programs can talk without driving the network card directly. Applications usually use sockets. A socket is one end of a communication channel that the kernel manages.

The kernel handles or coordinates many network tasks:

  • Creating and tracking sockets
  • Managing send and receive buffers
  • Connecting ports and addresses
  • Routing packets
  • Applying firewall rules
  • Handling retransmission for reliable protocols such as TCP
  • Delivering received data to the correct process
  • Interacting with network devices
1
2
3
4
5
6
7
Application
    ↓ socket API
Kernel networking stack
    ↓ driver
Network interface
    ↓
Physical or virtual network

The network interface is another shared resource. Many processes may send data through it, and buffers can fill when applications produce data faster than the network or the receiver can take it.

The socket and networking articles will later explain connection state, TCP segments, UDP datagrams, event-driven I/O, and the link between kernel buffers and application buffers.

Device management

Hardware devices differ a lot. A storage device, keyboard, network card, GPU, and sensor do not expose the same operations. The operating system uses device drivers to give a common interface where it can, and device-specific behavior where it must.

A driver may manage:

  • Device initialization
  • Register access
  • Interrupts
  • DMA transfers
  • Request queues
  • Device state
  • Error recovery
  • Power management

DMA, or direct memory access, lets a device move data to or from memory without the CPU copying every byte. The operating system must still set up the transfer, protect memory, and handle success or failure.

Devices can appear as special files or other operating-system interfaces. That appearance is an abstraction, not proof that the device acts exactly like a normal disk file. Device operations may block, fail, or order data differently than a regular file.

Security and protection

The operating system enforces walls between users, processes, devices, and privileged operations.

Important security mechanisms include:

  • User and group identity
  • File permissions
  • Access-control lists
  • Capabilities
  • Process isolation
  • Memory permissions
  • Privilege levels
  • Sandboxing
  • Resource limits
  • Security modules and audit records

Authentication answers who a user or process is. Authorization answers what that identity may do. The operating system mainly enforces authorization for local resources, though applications and services often set up their own authorization rules.

A process may have permission to open one file but not another. It may create a network connection but not bind to a privileged port. It may be blocked from reaching another process’s memory even if it knows the address.

Security checks are part of normal operating-system work. They can also add cost and create failure paths that applications must handle.

User space and kernel space

User space is the restricted place where ordinary programs run. Kernel space is the privileged place for the operating-system kernel and its trusted parts.

The CPU has modes that control which instructions and memory a piece of code may reach. When a user-space program needs a privileged service, it makes a system call. The processor switches mode, the kernel checks the request, does or starts the work, and then returns to user space.

The kernel must treat user-space input as untrusted, even when the program runs under the same user account. Pointers may be invalid, lengths may be malicious, and memory may change while the kernel is checking or using it. Checking system-call arguments is therefore both a correctness and a security duty.

The next article focuses on system calls and explains arguments, return values, transitions, validation, and common examples in detail.

Resource management and accounting

The operating system must track resources so it can set limits and decide how to schedule. It records information about processes, threads, open files, memory mappings, sockets, users, and devices.

Resource accounting can answer questions such as:

  • How much CPU time did a process use?
  • How much memory is resident?
  • How many file descriptors are open?
  • Which process owns a socket?
  • Which user opened a file?
  • How many processes are in a control group?

Accounting helps with debugging and operations, but it has limits. A process’s memory usage may include shared pages. A connection may use resources in several processes and devices. A service’s total database connections may be the sum of many process-local pools.

The numbers are useful only when read at the right scope.

Interprocess communication

Processes are isolated by default, but real systems need them to work together. The operating system provides interprocess communication mechanisms such as:

  • Pipes
  • Signals
  • Unix domain sockets
  • Network sockets
  • Shared memory
  • Message queues
  • File-based coordination

Each mechanism trades off copying, ordering, buffering, failure, and security in a different way.

For example, a pipe carries a byte stream between processes. Shared memory can skip copying large data, but it needs synchronization and clear ownership. A Unix domain socket can carry local messages and pass file descriptors.

IPC is another place where the operating system is both a provider and a wall. The processes must agree on a protocol, and each one must handle the other process going away or sending bad data.

The operating system is not the same as the kernel

The kernel is the privileged core that manages hardware, memory, processes, filesystems, networking, and security mechanisms. An operating system distribution includes much more:

1
2
3
4
5
6
7
8
9
10
Operating system environment
├── Kernel
├── System libraries
├── Init and service manager
├── Shells and command-line tools
├── Device management
├── Filesystem utilities
├── Network utilities
├── Package management
└── Applications and services

When engineers say “Linux,” they may mean the Linux kernel, a full Linux distribution, or the environment inside a container. Those are related but not identical.

The kernel provides the core mechanisms. User-space libraries and tools provide easy-to-use interfaces and operating behavior on top of them.

A request crosses multiple layers

Consider an application reading a file:

1
2
3
4
5
6
7
8
9
10
11
Application function
    ↓
Language runtime or standard library
    ↓
System-call interface
    ↓
Kernel file and filesystem code
    ↓
Device driver
    ↓
Storage device

Each layer has its own contract and its own ways to fail. The application may get an error from the library. The library may have turned an operating-system error into something else. The kernel may have returned data from the page cache without touching the device. The device may have reported an I/O error.

When debugging, the engineer may need to find which layer caused the behavior they see. A high-level error message often hides the full path.

A realistic production example

Imagine a service that cannot accept new client connections. The application reports a plain “server busy” error.

The investigation finds that the CPU is only moderately used and memory is available. The process has hit its file-descriptor limit because a code path failed to close connections after a protocol error. The kernel is still healthy, but the process cannot create the descriptors needed for new sockets.

The operating system set the limit and returned the failure. The application was responsible for closing resources and exposing enough metrics to spot the leak.

The fix is not simply to raise the limit. The team should close the connection on every path, add tests for protocol errors, watch descriptor usage, and pick a limit that gives enough room without hiding future leaks.

This example shows why the operating system and application share the job. The kernel enforces a boundary. The application must act correctly inside it.

How experienced engineers use the operating-system model

When an application acts strangely, experienced engineers place the symptom in the operating-system model.

They ask:

  • Is the process running, blocked, or stopped?
  • Is the thread waiting for CPU, a lock, a file, or a network event?
  • Is the memory mapped and resident?
  • Is the file operation using the page cache or the storage device?
  • Is the socket connected, buffered, or waiting for the peer?
  • Which identity and permissions apply?
  • Which resource limit could be involved?
  • Did the request cross into the kernel or another machine?
  • Which layer produced the error?

They then pick a tool that can see the layer in question: process inspection, system-call tracing, memory statistics, filesystem tools, socket inspection, packet capture, or a debugger.

The model does not replace evidence. It tells the engineer where to look.

Namespaces and cgroups form the boundary a container depends on

A container is not a separate operating system. It is a set of processes that the kernel shows a restricted and isolated view of the machine. Linux provides this isolation through namespaces and cgroups, and runtimes such as Docker and containerd are tools that set up those kernel features for you.

Namespaces change what a process can see. The mount namespace gives a process its own view of the filesystem tree. The PID namespace gives it its own numbering of processes, so the first process inside the container may look like PID 1 even though the host numbers it differently. The network namespace gives it its own interfaces, routes, and firewall rules. The UTS namespace controls the hostname. The IPC namespace separates System V and POSIX message queues. The user namespace maps the container’s root user to an unprivileged host user, which is how a container can look like it runs as root while holding no real privilege on the host.

cgroups, short for control groups, add to namespaces by limiting and accounting for resource use instead of hiding it. A cgroup can cap the CPU time, memory, and I/O bandwidth given to a group of processes, and it reports their total usage. Namespaces answer “what do I see” while cgroups answer “how much may I use”. A container boundary is both together: isolated views plus enforced limits.

The cost of a system call, and why io_uring reduces the crossings

Every time a program needs a privileged operation, it crosses from user space into the kernel through a system call. That crossing is not free. The processor must switch privilege mode, save and restore register state, and may need to clear parts of the CPU pipeline and translation caches. On a modern server a single syscall costs a few hundred nanoseconds to a microsecond, and you pay that cost on every read, write, accept, and poll.

For workloads that do huge numbers of small I/O operations, those crossings add up to real overhead. io_uring is a Linux interface built to cut them down. Instead of one system call per operation, a program submits many operations through shared memory ring buffers that both the application and the kernel can read. The kernel takes the submitted entries and fills completion entries without a per-operation mode switch. In this model the costly crossing happens a few times to drain a queue rather than once per operation.

io_uring does not remove the kernel from the path. It changes the cost of entering it, which is why it matters for high-throughput storage and networking services.

What a service cannot do from user space

A service running in user space cannot do the things that need privilege. It cannot program the network card, change another process’s page tables, reboot the machine, or read physical memory that has not been mapped to it. When such an operation is needed, the service must ask the kernel and accept the kernel’s decision.

This shapes daily engineering. A web server cannot bind to port 80 unless it holds the privilege or has been given the capability to do so. A process cannot be sure that data reached disk unless it calls fsync and the device honors it. A program cannot directly reserve a fixed slice of CPU; it can only ask for scheduling priority and let the kernel decide. The practical lesson is that most failure modes a backend hits are refusals or limits set at the kernel boundary, and the service must be written to handle that boundary instead of acting like it owns the machine.

/proc and /sys expose the live state a systems engineer inspects

The kernel shows its live state through two virtual filesystems, and a systems engineer reads them constantly. /proc shows information about processes and the kernel. Each running process has a directory under /proc/PID with files such as status, which reports memory and identity; maps, which shows mapped memory regions; fd, which lists open file descriptors; and cmdline, which shows the exact arguments. Reading /proc/loadavg, /proc/meminfo, and /proc/net gives a machine-wide view without special tools.

/sys, the sysfs interface, shows device, driver, and kernel subsystem state in a structured tree. It is where you inspect block devices, network interfaces, and tunable parameters. Neither filesystem stores data on disk; the kernel builds the contents when you read them. When you wonder why a process holds a socket open, why memory is counted a certain way, or why a device acts differently after a configuration change, these two trees are usually where the answer lives.

A process and a thread are different units of isolation

At the operating-system level a process and a thread are different units of management. A process is the unit of isolation: it owns an address space, open files, signal handlers, and identity. A thread is the unit of execution: it has its own stack and register state but shares the process’s address space and most resources with its sibling threads.

Two processes running the same binary are strongly isolated; one normally cannot read the other’s memory, and a crash in one does not corrupt the other. Two threads in the same process share memory by default; a write from one thread is seen by the others, which makes communication cheap but also lets a stray pointer or a data race damage the whole process. The kernel schedules threads, not processes, onto CPUs, which is why a multi-threaded program can keep several cores busy while a single-threaded one is limited to one at a time. Choosing between more processes and more threads is therefore a choice between stronger isolation and cheaper sharing.

Interview definitions

What does an operating system provide?

An operating system manages hardware and gives programs controlled ways to use the CPU, memory, storage, networking, devices, and interprocess communication. It does this through abstractions that make hardware easier to use, isolation that keeps processes apart, and policies like scheduling and limits that share resources safely.

What is the kernel?

The kernel is the privileged core of the operating system. It manages hardware, processes, memory, filesystems, networking, and protection, and it is where privileged operations are allowed. System libraries and systemd run in user space on top of it.

What is a process?

A process is a running instance of a program with its own address space, execution state, identity, and operating-system-managed resources. The same binary can become many processes with different PIDs, arguments, environment, and file descriptors.

What is user space vs kernel space?

User space is where ordinary programs run with restricted instructions and no direct access to privileged state. Kernel space is where the kernel runs with privilege. A system call is the controlled way to cross from one to the other.

What is a system call?

A system call is the controlled entry point that lets a user program ask the kernel to do a privileged operation, like opening a file or creating a process. The kernel checks the pointers and lengths at this boundary before touching protected state.

Interview follow-up questions

Why can an application not access hardware directly?

Direct access would let one program interfere with other programs, corrupt shared state, or skip security checks. The operating system provides controlled interfaces that check requests and coordinate access to shared hardware.

What is the difference between a process and a program?

A program is the code and data stored in an executable. A process is a running instance of that program with its own execution state, address space, identity, and resources.

What happens when a program needs a privileged operation?

It enters the kernel through a system call. The kernel checks the arguments and permissions, does or schedules the operation, and returns a result or error to user space.

Why does the kernel validate system-call arguments?

User-space pointers and lengths cannot be trusted. They may be invalid, point outside the process, change during the operation, or be made on purpose to bypass checks. Checking them protects correctness and the kernel’s security boundary.

Is the kernel the entire operating system?

No. The kernel is the privileged core. A complete operating-system environment also includes system libraries, service managers, shells, device tools, package management, and other user-space programs.

Why can a file read be fast sometimes and slow at other times?

The data may already be in the kernel’s page cache, or the system may need to read it from storage. Memory pressure, storage load, filesystem behavior, and concurrent access can also change the latency.

Common misconceptions

“The operating system only manages CPU and memory.”

It also manages files, storage, network interfaces, devices, security, process communication, timers, resource limits, and many other shared services.

“A process is just a program currently running.”

A process includes execution state, an address space, identity, open resources, limits, and relationships with other processes.

“Kernel space is just another folder.”

Kernel space is a privileged execution environment protected by the processor and operating system. It is not a directory or ordinary storage location.

“A system call is the same as a normal function call.”

A normal function call stays within the current process and privilege level. A system call crosses from user space into the privileged kernel and follows a different validation and execution path.

“The operating system hides all hardware behavior.”

It hides many details through abstractions, but hardware latency, device errors, cache behavior, capacity limits, and ordering guarantees can still affect programs.

“If the kernel reclaims resources after a crash, application cleanup does not matter.”

The kernel can reclaim many local resources, but it cannot undo every external effect. Persistent data, messages, remote requests, and distributed state still need application-level recovery.

Summary

The operating system is the layer that manages shared hardware and gives programs controlled services. It manages processes, scheduling, memory, files, storage, networking, devices, security, resource limits, and interprocess communication.

User space and kernel space form an important protection boundary. Programs ask for privileged operations through system calls, and the kernel checks those requests before touching protected state or hardware.

The operating system gives useful abstractions, but the details beneath them can still affect correctness, performance, security, and failure behavior. When debugging a system, place the symptom in the operating-system model and find which layer caused the result you see.

If you want to build this later

Build a small Linux process-inspection tool that reports the operating-system resources of a target process.

Start with the process ID and command line. Then read information from /proc such as memory usage, open file descriptors, CPU time, and status. Add a mode that watches the process over time and reports changes.

The goal is not to rebuild every feature of ps or top. It is to tie an ordinary process to the operating-system services introduced in this article and to prepare for the deeper articles about system calls, processes, memory, files, and resource limits.

This post is licensed under CC BY 4.0 by the author.