Demystifying Linux Processes, Threads, IPC, and Scheduling
This article provides a comprehensive overview of Linux fundamentals, covering process and thread concepts, the fork and exec system calls, various inter‑process communication mechanisms, memory layout, scheduling algorithms such as O(1) and CFS, synchronization primitives, and the boot sequence, all illustrated with code snippets and diagrams.
Basic Concepts
Linux treats a process as an independent execution context that contains its own program counter, memory image, and file descriptors. Each process is represented in the kernel by a task_struct descriptor, which stores scheduling parameters, open files, signals, registers, and other bookkeeping information.
When a process creates a child, the fork system call duplicates the parent’s memory image, file descriptors, and registers. The child receives a new PID, while the parent receives the child’s PID. After fork, the parent and child run independently; changes in one’s memory are not visible to the other unless shared memory is used.
Linux also supports daemon processes ( daemon) that run in the background, and specialized daemons such as the Cron daemon, which wakes up periodically to execute scheduled jobs.
Cron is a daemon that can perform regular system maintenance or backups. On macOS the equivalent is launchd , and on Windows it is the Task Scheduler.
Linux Inter‑Process Communication
Signals
Signals are the oldest IPC mechanism inherited from UNIX. A process can send asynchronous signals (e.g., SIGINT, SIGKILL, SIGSTOP) to another process to request termination, stop execution, or notify of an event. Some signals cannot be ignored ( SIGKILL, SIGSTOP).
Pipes
A pipe creates a unidirectional byte stream between two processes. The writer writes to the pipe, the reader reads from it. In a shell pipeline such as sort <f | head, the shell creates a pipe, runs sort with its standard output connected to the pipe’s write end, and runs head with its standard input connected to the pipe’s read end.
sort <f | headShared Memory
Processes can share a memory segment using the System V API: shmget() to create or obtain a segment, shmat() to attach it, shmdt() to detach, and shmctl() for control operations. Shared memory provides the fastest IPC because data does not need to be copied.
FIFO (Named Pipe)
A FIFO behaves like a regular pipe but is represented as a special file in the filesystem, allowing unrelated processes to open it at different times. Data is read in the order it was written (first‑in‑first‑out).
Message Queues
Message queues store messages in kernel space, identified by an IPC key. They can operate in strict (FIFO) mode or non‑strict mode where ordering is not guaranteed.
Sockets
Sockets provide bidirectional network communication. Linux supports stream sockets (TCP), datagram sockets (UDP), sequential‑packet sockets, raw sockets, and others. They are used for both local IPC (UNIX domain sockets) and network communication.
Process Management System Calls
The most important calls are: fork() – creates a child process. exec() family (e.g., execl, execve) – replaces the current image with a new executable without changing the PID. waitpid() – waits for a specific child to terminate. exit() – terminates the calling process, returning a status code.
Other useful calls include pause, nice, ptrace, kill, pipe, mkfifo, sigaction, msgctl, and semctl.
Process Memory Layout
A Linux process address space consists of several segments:
Code segment (text) – read‑only executable code.
Data segment – initialized global and static variables.
BSS segment – zero‑initialized global and static variables.
Heap – dynamically allocated memory via malloc / realloc.
Stack – automatic variables and function call frames.
When fork is performed, the kernel uses a copy‑on‑write strategy: the child receives a new page table that initially points to the parent’s pages marked read‑only. Only when either process writes to a page does the kernel allocate a private copy.
Linux Scheduling
Linux schedules threads (not processes) using three classes: real‑time FIFO, real‑time round‑robin, and normal (time‑sharing). Each thread has a nice value ranging from –20 (high priority) to +19 (low priority) that influences its static priority.
The historic O(1) scheduler organized runnable tasks into two arrays (active and expired) each containing 140 priority lists. Tasks moved between the arrays based on time‑slice expiration and blocking state.
Modern kernels use the Completely Fair Scheduler (CFS). CFS stores runnable tasks in a red‑black tree ordered by virtual runtime; the leftmost node (the task that has used the least CPU) is selected next. Insertion is O(log N), where N is the number of runnable tasks.
Synchronization Primitives
Early Linux kernels used a single Big Kernel Lock (BKL). Modern kernels provide finer‑grained primitives:
Atomic operations ( atomic_set, atomic_read) for lock‑free counters.
Spinlocks – busy‑wait loops used in interrupt context.
Mutexes and semaphores – sleep‑based locks that can be taken without busy‑waiting.
Read‑write locks, futexes, and memory barriers for ordering.
Linux Boot Sequence
On power‑on, the BIOS performs POST, then loads the first sector (MBR) into memory and executes it. The bootloader loads the kernel image, switches to protected mode, and jumps to the kernel’s entry point.
The kernel initializes hardware, sets up memory management, creates the initial process (PID 0, the idle task), then forks the first user‑space process (PID 1, init). init runs startup scripts ( /etc/rc), which in turn spawn getty on each terminal. getty prompts for a username, launches /bin/login, which authenticates against /etc/passwd and finally starts the user’s shell.
Key Takeaways
Understanding how fork, exec, and various IPC mechanisms work is essential for writing robust Linux applications. The kernel’s copy‑on‑write optimization, the evolution from O(1) to CFS scheduling, and the rich set of synchronization primitives enable high‑performance, concurrent software. Finally, the boot process illustrates how the low‑level firmware hands control to the kernel, which then builds the user‑space environment.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
