Recent from talks
Contribute something
Nothing was collected or created yet.
Process (computing)
View on Wikipedia
Scheduling, Preemption, Context Switching
In computing, a process is the instance of a computer program that is being executed by one or many threads. There are many different process models, some of which are light weight, but almost all processes (even entire virtual machines) are rooted in an operating system (OS) process which comprises the program code, assigned system resources, physical and logical access permissions, and data structures to initiate, control and coordinate execution activity. Depending on the OS, a process may be made up of multiple threads of execution that execute instructions concurrently.[1][2]
While a computer program is a passive collection of instructions typically stored in a file on disk, a process is the execution of those instructions after being loaded from the disk into memory. Several processes may be associated with the same program; for example, opening up several instances of the same program often results in more than one process being executed.
Multitasking is a method to allow multiple processes to share processors (CPUs) and other system resources. Each CPU (core) executes a single process at a time. However, multitasking allows each processor to switch between tasks that are being executed without having to wait for each task to finish (preemption). Depending on the operating system implementation, switches could be performed when tasks initiate and wait for completion of input/output operations, when a task voluntarily yields the CPU, on hardware interrupts, and when the operating system scheduler decides that a process has expired its fair share of CPU time (e.g, by the Completely Fair Scheduler of the Linux kernel).
A common form of multitasking is provided by CPU's time-sharing that is a method for interleaving the execution of users' processes and threads, and even of independent kernel tasks – although the latter feature is feasible only in preemptive kernels such as Linux. Preemption has an important side effect for interactive processes that are given higher priority with respect to CPU bound processes, therefore users are immediately assigned computing resources at the simple pressing of a key or when moving a mouse. Furthermore, applications like video and music reproduction are given some kind of real-time priority, preempting any other lower priority process. In time-sharing systems, context switches are performed rapidly, which makes it seem like multiple processes are being executed simultaneously on the same processor. This seemingly-simultaneous execution of multiple processes is called concurrency.
For security and reliability, most modern operating systems prevent direct communication between independent processes, providing strictly mediated and controlled inter-process communication.
Representation
[edit]

In general, a computer system process consists of (or is said to own) the following resources:
- An image of the executable machine code associated with a program.
- Memory (typically some region of virtual memory); which includes the executable code, process-specific data (input and output), a call stack (to keep track of active subroutines and/or other events), and a heap to hold intermediate computation data generated during run time.
- Operating system descriptors of resources that are allocated to the process, such as file descriptors (Unix terminology) or handles (Windows), and data sources and sinks.
- Security attributes, such as the process owner and the process' set of permissions (allowable operations).
- Processor state (context), such as the content of registers and physical memory addressing. The state is typically stored in computer registers when the process is executing, and in memory otherwise.[1]
The operating system holds most of this information about active processes in data structures called process control blocks. Any subset of the resources, typically at least the processor state, may be associated with each of the process' threads in operating systems that support threads or child processes.
The operating system keeps its processes separate and allocates the resources they need, so that they are less likely to interfere with each other and cause system failures (e.g., deadlock or thrashing). The operating system may also provide mechanisms for inter-process communication to enable processes to interact in safe and predictable ways.
Multitasking and process management
[edit]A multitasking operating system may just switch between processes to give the appearance of many processes executing simultaneously (that is, in parallel), though in fact only one process can be executing at any one time on a single CPU (unless the CPU has multiple cores, then multithreading or other similar technologies can be used).[a]
It is usual to associate a single process with a main program, and child processes with any spin-off, parallel processes, which behave like asynchronous subroutines. A process is said to own resources, of which an image of its program (in memory) is one such resource. However, in multiprocessing systems many processes may run off of, or share, the same reentrant program at the same location in memory, but each process is said to own its own image of the program.
Processes are often called "tasks" in embedded operating systems. The sense of "process" (or task) is "something that takes up time", as opposed to "memory", which is "something that takes up space".[b]
The above description applies to both processes managed by an operating system, and processes as defined by process calculi.
If a process requests something for which it must wait, it will be blocked. When the process is in the blocked state, it is eligible for swapping to disk, but this is transparent in a virtual memory system, where regions of a process's memory may be really on disk and not in main memory at any time. Even portions of active processes/tasks (executing programs) are eligible for swapping to disk, if the portions have not been used recently. Not all parts of an executing program and its data have to be in physical memory for the associated process to be active.
Process states
[edit]
An operating system kernel that allows multitasking needs processes to have certain states. Names for these states are not standardised, but they have similar functionality.[1]
- First, the process is "created" by being loaded from a secondary storage device (hard disk drive, CD-ROM, etc.) into main memory. After that the process scheduler assigns it the "waiting" state.
- While the process is "waiting", it waits for the scheduler to do a so-called context switch. The context switch loads the process into the processor and changes the state to "running" while the previously "running" process is stored in a "waiting" state.
- If a process in the "running" state needs to wait for a resource (wait for user input or file to open, for example), it is assigned the "blocked" state. The process state is changed back to "waiting" when the process no longer needs to wait (in a blocked state).
- Once the process finishes execution, or is terminated by the operating system, it is no longer needed. The process is removed instantly or is moved to the "terminated" state. When removed, it just waits to be removed from main memory.[1][3]
Inter-process communication
[edit]When processes need to communicate with each other they must share parts of their address spaces or use other forms of inter-process communication (IPC). For instance in a shell pipeline, the output of the first process needs to pass to the second one, and so on. Another example is a task that has been decomposed into cooperating but partially independent processes which can run simultaneously (i.e., using concurrency, or true parallelism – the latter model is a particular case of concurrent execution and is feasible whenever multiple CPU cores are available for the processes that are ready to run).
It is even possible for two or more processes to be running on different machines that may run different operating system (OS), therefore some mechanisms for communication and synchronization (called communications protocols for distributed computing) are needed (e.g., the Message Passing Interface {MPI}).
History
[edit]By the early 1960s, computer control software had evolved from monitor control software, for example IBSYS, to executive control software. Over time, computers got faster while computer time was still neither cheap nor fully utilized; such an environment made multiprogramming possible and necessary. Multiprogramming means that several programs run concurrently. At first, more than one program ran on a single processor, as a result of underlying uniprocessor computer architecture, and they shared scarce and limited hardware resources; consequently, the concurrency was of a serial nature. On later systems with multiple processors, multiple programs may run concurrently in parallel.
Programs consist of sequences of instructions for processors. A single processor can run only one instruction at a time: it is impossible to run more programs at the same time. A program might need some resource, such as an input device, which has a large delay, or a program might start some slow operation, such as sending output to a printer. This would lead to processor being "idle" (unused). To keep the processor busy at all times, the execution of such a program is halted and the operating system switches the processor to run another program. To the user, it will appear that the programs run at the same time (hence the term "parallel").
Shortly thereafter, the notion of a "program" was expanded to the notion of an "executing program and its context". The concept of a process was born, which also became necessary with the invention of re-entrant code. Threads came somewhat later. However, with the advent of concepts such as time-sharing, computer networks, and multiple-CPU shared memory computers, the old "multiprogramming" gave way to true multitasking, multiprocessing and, later, multithreading.
See also
[edit]Notes
[edit]- ^ Some modern CPUs combine two or more independent processors in a multi-core configuration and can execute several processes simultaneously. Another technique called simultaneous multithreading (used in Intel's Hyper-threading technology) can simulate simultaneous execution of multiple processes or threads.
- ^ Tasks and processes refer essentially to the same entity. And, although they have somewhat different terminological histories, they have come to be used as synonyms. Today, the term process is generally preferred over task, except when referring to "multitasking", since the alternative term, "multiprocessing", is too easy to confuse with multiprocessor (which is a computer with two or more CPUs).
References
[edit]- ^ a b c d Silberschatz, Abraham; Cagne, Greg; Galvin, Peter Baer (2004). "Chapter 4. Processes". Operating system concepts with Java (Sixth ed.). John Wiley & Sons. ISBN 0-471-48905-0.
- ^ Vahalia, Uresh (1996). "Chapter 2. The Process and the Kernel". UNIX Internals: The New Frontiers. Prentice-Hall Inc. ISBN 0-13-101908-2.
- ^ Stallings, William (2005). Operating Systems: internals and design principles (5th ed.). Prentice Hall. ISBN 0-13-127837-1. (particularly chapter 3, section 3.2, "process states", including figure 3.9 "process state transition with suspend states")
Further reading
[edit]- Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau (2014). "Operating Systems: Three Easy Pieces". Arpaci-Dusseau Books. Relevant chapters: Abstraction: The Process The Process API
- Gary D. Knott (1974) A proposal for certain process management and intercommunication primitives ACM SIGOPS Operating Systems Review. Volume 8, Issue 4 (October 1974). pp. 7 – 44
External links
[edit]
Media related to Process (computing) at Wikimedia Commons- Online Resources For Process Information
- Computer Process Information Database and Forum
- Process Models with Process Creation & Termination Methods Archived 2021-02-06 at the Wayback Machine
Process (computing)
View on GrokipediaFundamentals
Definition and Characteristics
In computing, a process is defined as a program in execution, serving as the fundamental unit of work within an operating system. It represents an active entity that encapsulates the program's code (text segment), data (including global variables), stack (for temporary data and activation records), heap (for dynamic memory allocation), and current execution state, such as the program counter and CPU registers.[7][8] This structure allows the operating system to manage multiple such instances concurrently, providing each with the illusion of exclusive access to system resources. Key characteristics of a process include its independent virtual address space, which isolates it from other processes to enhance system stability and security by preventing interference with shared resources. This address space typically divides into user and kernel regions, mapped to physical memory via mechanisms like page tables. Additionally, a process maintains CPU registers (e.g., program counter for the next instruction, stack pointer, and general-purpose registers), open files, I/O status, and signals for handling events. The operating system tracks these attributes in a process control block, a kernel data structure essential for management.[8] A program, in contrast, is a passive, static entity consisting of executable code stored on disk, lacking any runtime context or allocated resources. A process, however, is a dynamic instantiation of that program, activated upon loading into memory and assigned execution privileges by the operating system. This distinction underscores the shift from inert instructions to an active computational activity.[7][8] During execution, the operating system allocates resources to a process on an exclusive basis, including slices of CPU time via scheduling, portions of memory for its address space, and access to I/O devices and files. These allocations ensure controlled, efficient utilization while maintaining isolation, with resources reclaimed upon process completion to prevent waste.[7][8]Process Control Block
The Process Control Block (PCB) is a kernel data structure that encapsulates all information required by the operating system to manage an individual process, serving as the central repository for process-specific details.[9] It includes the process identifier (PID), which uniquely identifies the process within the system; the current process state, indicating whether it is ready, running, or blocked; the program counter, which holds the address of the next instruction to execute; and CPU registers, capturing the processor's state such as general-purpose registers and stack pointers.[10] Additional fields encompass memory-management details like limits on virtual memory allocation and pointers to page tables for address translation, accounting information such as accumulated CPU time and resource usage, and I/O status, including open files and pending operations.[11] These components ensure the kernel can track and control process execution without relying on user-space data.[9] The PCB plays a critical role in operating system operations by enabling efficient context switching and informed scheduling decisions. During context switching, the kernel saves the executing process's CPU context—including registers and the program counter—into its PCB and restores the context from another process's PCB, allowing seamless transitions between processes.[9] For scheduling, the PCB provides essential data like process state and priority, which the scheduler uses to select the next process for execution from the ready queue.[9] This centralized storage facilitates multitasking by maintaining isolation and restorability of each process's environment.[10] Implementations of the PCB vary across operating systems to suit their architectures and requirements. In Unix-like systems such as Linux, the PCB is realized as thetask_struct structure in the kernel, which includes fields for PID (pid), state (state), a memory descriptor (mm) pointing to page tables and virtual memory areas, CPU registers via the thread_info, accounting metrics like CPU usage (utime and stime), and I/O-related lists for file descriptors. In contrast, Microsoft's Windows uses the EPROCESS structure, featuring UniqueProcessId for PID, process flags for state (e.g., active or terminated), embedded KPROCESS for CPU context including registers, VadRoot for virtual address descriptors and page table management, quota usage for accounting, and counters for I/O operations like read/write transfers.[12]
Regarding memory management, the PCB integrates pointers to the process's page tables, which map virtual addresses to physical frames, along with allocation limits to enforce boundaries and prevent overflow.[11] In Linux's task_struct, the mm_struct field links to the page directory base (via pgd), enabling the memory management unit (MMU) to load the correct translation during context switches. Similarly, Windows' EPROCESS contains offsets to the process environment block (PEB) and directory table base (CR3 register value) for page table access, supporting demand-paging and protection.[12] These elements allow the kernel to handle virtual memory isolation per process without global interference.[11]
Process Lifecycle
Creation and Initialization
In Unix-like operating systems, new processes are typically created using thefork() system call, which duplicates the calling process to produce an identical child process that shares the parent's code, data, and most resources.[13][14] The child process then often invokes one of the exec() family of functions, such as execve(), to replace its memory image with a new program loaded from an executable file, while retaining the process identifier and other inherited attributes.[15][16] The fork-exec model originated from early Unix designs. Modern Unix-like systems enable efficient process creation using copy-on-write techniques, which allow the parent and child to share memory pages until modifications occur.[13][17] In contrast, Microsoft Windows employs the CreateProcess() API function, which creates a new process and its primary thread in a single call, specifying the executable image, command line, and initial environment without requiring a separate duplication step.[18][19]
Upon creation, the operating system allocates a Process Control Block (PCB) for the new process to store essential metadata, such as the process identifier, register states, and memory management information.[20][21] The program code and data are then loaded into the process's virtual address space, with initial stack and heap regions allocated to support execution and dynamic memory needs.[22][23] The process is initialized in a "ready" state, placed on the scheduler's ready queue, and inherits resources from its parent, including open file descriptors and environment variables that define the execution context, such as the system path and current working directory.[20][15][24]
The creation establishes a parent-child relationship, forming process hierarchies where each child is linked to its creator, often visualized as a tree structure with the init process (PID 1) as the root in Unix-like systems.[25] Incomplete handling of child exit status by the parent can result in zombie processes, which occupy PCB entries until reaped.[26] This inheritance model ensures resource continuity while allowing children to modify their environment independently after setup.[15]
States and Transitions
In operating systems, a process progresses through a series of distinct states during its lifecycle, managed by the kernel to ensure efficient resource allocation and execution. The standard model, often referred to as the five-state process model, defines these states as New, Ready, Running, Waiting (or Blocked), and Terminated, allowing the operating system to track and transition processes based on system events and resource availability.[27][28] The New state represents the initial phase where the process is being created, involving allocation of resources like memory and initialization of the process control block, but it has not yet been admitted to the ready queue. Once creation completes, the process transitions to the Ready state, where it awaits allocation of CPU time and is placed in the ready queue, a data structure maintained by the operating system to hold processes eligible for execution. In the Running state, the process is actively executing on the CPU, performing instructions until an event interrupts it. The Waiting state occurs when the process is blocked, typically awaiting an I/O operation, timer expiration, or another event, and is moved to an I/O or device queue. Finally, the Terminated state marks the end of execution, where the process has completed normally or been abnormally killed, releasing its resources back to the system.[27][29][30] State transitions are triggered by specific events and managed through kernel mechanisms, forming a logical flow that can be visualized as a directed graph. From New to Ready, admission occurs upon successful initialization; from Ready to Running, the scheduler dispatches the process via a context switch when the CPU becomes available. The Running state can lead back to Ready through preemption (e.g., time slice expiration via timer interrupt) or to Waiting via a system call for I/O or blocking operation. Upon event completion, such as I/O finish signaled by a hardware interrupt, the process moves from Waiting to Ready. Termination transitions from Running (or sometimes Waiting) to Terminated, often initiated by a system call like exit or an unhandled error. These transitions rely on queues like the ready queue for dispatch candidates and device queues for blocked processes, ensuring orderly progression without overlap.[28][30][31] Variations exist across operating systems, such as the seven-state model, which extends the five-state model by adding Suspended Ready and Suspended Blocked states to handle scenarios where processes are temporarily removed from main memory (swapped out) for resource conservation in memory-constrained environments. In this model, a running process can be suspended to Suspended Ready by the OS or another process, and later resumed to Ready; similarly, a blocked process can enter Suspended Blocked and return to Blocked upon resumption. This extension is common in systems supporting virtual memory and multitasking under load, though the core five states remain foundational in most modern kernels like those in Unix-like systems.[28][32]Termination and Cleanup
Processes terminate through several distinct mechanisms, each triggering specific operating system actions to ensure orderly conclusion of execution. Normal termination occurs when a process reaches the end of its main function or explicitly calls theexit() system call, prompting the operating system to initiate deletion by releasing resources and updating process tables.[33] Abnormal termination arises from runtime errors, such as division by zero or invalid memory access, or from receiving a termination signal like SIGTERM sent by another process via the kill() system call.[33] Forced termination is imposed by the operating system itself, typically in response to resource exhaustion, security violations, or system-wide shutdown commands, bypassing the process's voluntary exit.[33] This final transition moves the process to a terminated state, where it no longer executes but awaits full reclamation.[4]
Following termination, the operating system executes a comprehensive cleanup routine to reclaim resources and maintain system integrity. This includes deallocating the process's virtual memory address space, closing all open files and network sockets, releasing any acquired locks or semaphores, and flushing buffered I/O data to disk.[34] The process control block (PCB) is updated to reflect the ended status, and kernel structures associated with the process, such as file descriptors and signal handlers, are freed.[4] To notify the parent process, the operating system sets a flag in the child's PCB; the parent can then invoke the wait() or waitpid() system call to retrieve termination details and complete the reaping process, preventing indefinite resource holds.[33]
A key challenge in termination arises with zombie and orphan processes, which require specific handling to avoid resource leaks. A zombie process forms when a child terminates but its parent has not yet called wait() to reap it; the child releases most resources but retains a minimal entry in the kernel's process table, including its process ID (PID) and exit status, until the parent acknowledges completion.[35] Failure to reap zombies can exhaust the process table, limiting new process creation; if the parent process terminates without reaping its children, the zombies become orphans and are reaped by the init process (or equivalent).[36] Orphan processes occur if the parent terminates before the child; the child is then adopted by the system init process (PID 1), which assumes responsibility for reaping it upon the child's eventual termination, ensuring no processes remain unparented.[35]
The exit status provides a mechanism for inter-process signaling during termination, conveying the outcome to the parent. Passed as an integer argument to exit(status), it conventionally uses 0 to indicate successful completion and non-zero values for errors, with specific codes often defined by applications or standards like POSIX.[37] The parent retrieves this status via wait(), shifted left by 8 bits in some implementations to distinguish exit from signal termination, allowing scripts or programs to react accordingly—such as logging failures or chaining dependent tasks.[4] This status is preserved in the zombie's PCB until reaped, ensuring reliable communication even if the parent delays.[35]
Process Management
Scheduling and Dispatching
In operating systems, scheduling refers to the method by which the kernel selects processes from the ready queue to execute on the CPU, aiming to optimize resource allocation and system performance.[38] Dispatching then follows as the kernel's mechanism to allocate the CPU to the chosen process by saving the state of the currently running process and restoring the state of the selected one.[39] This process ensures efficient multitasking while balancing competing objectives.[38] The primary goals of CPU scheduling include maximizing CPU utilization, which measures the percentage of time the CPU is busy executing processes rather than idling; maximizing throughput, defined as the number of processes completed per unit time; minimizing turnaround time, the interval from process submission to completion; minimizing waiting time, the total time a process spends in the ready queue; and minimizing response time, the duration from request submission to the first output for interactive processes.[40] These objectives often trade off against each other, with batch systems prioritizing throughput and turnaround time, while interactive systems emphasize response time.[41] Scheduling is categorized by timing levels: long-term scheduling decides the degree of multiprogramming by admitting new processes to the system; medium-term scheduling handles swapping processes in and out of memory to manage resource contention; and short-term scheduling, or CPU scheduling, selects the next process to run from the ready queue.[42] Algorithms are further classified as preemptive, where the operating system can interrupt a running process to allocate the CPU to another (e.g., due to a timer interrupt), or non-preemptive, where a process runs until it voluntarily yields the CPU, such as upon completion or I/O request.[43] Preemptive scheduling supports better responsiveness in time-sharing environments but incurs higher overhead from frequent context switches.[44] Common short-term scheduling algorithms include First-Come, First-Served (FCFS), which executes processes in the order of their arrival, leading to simple implementation but potential convoy effects where short processes wait behind long ones.[45] Shortest Job First (SJF) selects the process with the smallest estimated CPU burst time next, minimizing average waiting time for non-preemptive cases and proven optimal under certain assumptions, though it requires accurate burst predictions.[46] Round Robin (RR) allocates a fixed time quantum (typically 10-100 ms) to each process in a cyclic manner, using preemption to ensure fairness and low response times in interactive systems, with performance degrading if the quantum is too small due to context switch overhead.[47] Priority scheduling assigns execution order based on process priority levels, often incorporating aging to prevent indefinite starvation of low-priority processes, but it can lead to priority inversion if not managed carefully.[48] Dispatching occurs when the scheduler identifies the next process, at which point the kernel dispatcher saves the context (registers, program counter, and process state) of the current process to its Process Control Block and loads the context of the selected process, enabling seamless CPU reassignment.[9] This mechanism is invoked on events like timer expirations, I/O completions, or process terminations.[39] Key performance metrics for evaluating scheduling effectiveness include turnaround time, calculated as: for each process, representing the total time from submission to finish.[49] Waiting time for a process is then: where burst time is the actual CPU execution duration, and the average waiting time across processes is: [50] These metrics quantify fairness and efficiency, with algorithms like SJF often yielding lower averages in simulations compared to FCFS.[47]Multitasking and Context Switching
Multitasking in operating systems enables the concurrent execution of multiple processes, allowing a single processor to handle several tasks by rapidly alternating between them. This concurrency is achieved through two primary models: cooperative multitasking, where processes voluntarily yield control to the operating system after completing a portion of their work, and preemptive multitasking, where the operating system forcibly interrupts a running process using hardware timers to allocate CPU time to others.[51][52] Multitasking can further be classified as single-user, supporting multiple processes for one user on a personal system like early Windows versions, or multi-user, accommodating simultaneous access by multiple users on shared systems like Unix.[53][54] Context switching is the core mechanism underlying multitasking, involving the operating system saving the state of the currently executing process—such as register values, program counter, and memory management information—into its Process Control Block (PCB) before loading the state of the next process from its PCB to resume execution.[55] This switch is typically triggered by the scheduler when a process's time slice expires or it blocks for I/O. However, it incurs overhead from flushing processor caches and the Translation Lookaside Buffer (TLB), as these hardware structures hold process-specific data that must be invalidated or reloaded to prevent interference between address spaces, leading to performance penalties from cache misses and TLB refills upon resumption.[56][57] In time-sharing systems, context switching creates the illusion of simultaneous execution by allocating short time slices—often milliseconds—to each process, enabling multiple users or tasks to appear to run concurrently on a single processor despite sequential actual execution.[58] This approach, foundational to modern interactive computing, maximizes resource utilization and responsiveness in multi-user environments.[59] Modern enhancements to multitasking leverage hardware advancements for improved efficiency and parallelism. Hyper-Threading Technology, introduced by Intel, allows a single physical core to appear as multiple logical processors by duplicating architectural state while sharing execution resources, facilitating faster context switches and better utilization during stalls.[60] In multi-core processors, true parallelism emerges as independent cores execute separate processes simultaneously without the need for frequent switching, scaling multitasking beyond the limitations of single-core time-sharing.[61] The performance impact of context switching includes latency typically ranging from 5 to 20 microseconds on modern hardware, encompassing direct costs like state save/restore and indirect costs from cache and TLB disruptions, which can degrade throughput if switches occur too frequently.[62][47]Inter-Process Communication
Communication Mechanisms
In computing, processes communicate and coordinate through various mechanisms that enable data exchange and event notification while maintaining system stability. These methods, primarily defined in POSIX standards, allow unrelated processes to interact without direct memory access, supporting both local and networked environments. Seminal work on interprocess communication in Unix systems emphasized reliable, kernel-mediated channels to facilitate modularity and portability across processes.[63] Shared memory provides a high-performance mechanism where multiple processes map the same region of physical memory into their virtual address spaces, enabling direct data sharing. This approach, supported by POSIX through functions likeshm_open() and mmap(), creates a shared memory object identified by a name, which processes can open and attach independently. Once mapped, processes read and write to the shared region as if it were private memory, but this requires careful synchronization to prevent race conditions where concurrent access leads to inconsistent data. Shared memory is particularly efficient for large data transfers in applications like databases or multimedia processing, as it avoids kernel involvement in each data movement.[64][65]
Message passing offers a structured alternative, where processes exchange fixed or variable-sized messages via kernel-managed buffers, decoupling sender and receiver. POSIX message queues, created and accessed via mq_open(), allow processes to send and receive priority-ordered messages asynchronously, with the queue acting as an intermediary to handle blocking or non-blocking operations. This mechanism supports multiple readers and writers, making it suitable for producer-consumer patterns in distributed systems. Pipes and first-in-first-out (FIFO) devices extend message passing for stream-oriented data: unnamed pipes, created by pipe(), provide unidirectional communication between related processes, such as parent and child after a fork(), with one end for writing and the other for reading. Named pipes, or FIFOs, use mkfifo() to create filesystem-visible entries, enabling unrelated processes to connect via a common path, thus broadening applicability beyond process hierarchies.[66][67][68][69][70]
Sockets, originating from Berkeley Unix, facilitate both local (Unix domain) and network (Internet domain) message passing through a socket API that abstracts transport protocols like TCP or UDP. A server process creates a socket with socket(), binds it to an address and port using bind(), and listens for connections via listen(), while clients initiate communication with connect(). Data is exchanged bidirectionally using send() and recv(), supporting reliable, ordered delivery over networks. This mechanism underpins client-server architectures, such as web services where a browser process connects to a server process across machines.
Signals provide an asynchronous, lightweight notification mechanism for event signaling between processes, without data transfer. POSIX defines signals like SIGTERM, sent via kill() to request graceful termination, allowing the receiving process to handle or ignore it for cleanup. Signals are delivered by the kernel interrupting the target process, useful for scenarios like error reporting or job control, but they carry limited information—typically just an integer code—requiring supplementary mechanisms for detailed communication. For instance, Unix shells chain commands using unnamed pipes, as in ls | grep .txt, where the output of ls streams directly into grep for filtering. Similarly, socket-based client-server examples demonstrate a web client sending HTTP requests to a server process, which responds with processed data.[71][72]
