An operating system sits between applications and hardware. It provides abstractions such as a process, virtual address space, file descriptor, and socket, while arbitrating access to limited processors, memory, storage, and devices.
Processes and threads
A process is an execution environment with its own address space and resources. A thread is a schedulable sequence of execution with registers and a stack. Threads in one process usually share the process's memory, which makes communication convenient and synchronization essential. The kernel can pause one thread and run another; that context switch saves and restores enough state to resume each later.
Virtual memory
Programs use virtual addresses. Hardware translates them through page tables, and the kernel manages mappings and permissions. A page fault occurs when an access needs kernel attention, for example because a page is not currently mapped in memory or because permissions forbid the access. The kernel may load or create a page, update mappings, or deliver an error. A fault is a mechanism, not automatically a bug.
System calls and I/O
An application asks the kernel to perform privileged operations through system calls. For Linux read(fd, buffer, count), the call attempts to copy up to count bytes from the open file description referenced by fd; a short read is allowed, and zero commonly signals end of file. The call can complete from cached data, wait for a device, return fewer bytes than requested, or fail. The interface describes behavior without promising a specific path through hardware for every call.
Concurrency needs rules
When threads share mutable state, the result can depend on timing. Locks, condition variables, semaphores, and atomic operations express rules for coordinating access. A correct design must consider lock ordering, cancellation, timeouts, and what happens when a thread fails while holding shared state.
The Linux read(2) manual page documents the system call contract; Operating Systems: Three Easy Pieces builds the broader model.