Loading content...
Every process that has ever executed on a computer—from the simplest shell script to the most complex database server—began its existence in a single, fundamental state: New. This state represents the critical transition point where a static program transforms into a dynamic, schedulable entity capable of competing for system resources.
The New state is far more than a mere bookkeeping label. It represents a complex orchestration of memory allocation, data structure initialization, security validation, and resource reservation. Understanding this state deeply reveals how operating systems balance resource efficiency with process creation speed, and how design decisions at this level ripple through system performance.
By the end of this page, you will understand the complete anatomy of process creation—from the moment a user requests program execution to the instant the process is admitted to the Ready queue. You'll learn about PCB initialization, memory mapping, resource allocation strategies, and admission control mechanisms that prevent system overload.
The New state represents a process that has been created but has not yet been admitted to the pool of executable processes. A process in this state exists in a liminal space—it has been acknowledged by the operating system, but it cannot yet compete for CPU time.
A process is in the New state when:
This state exists because process creation is not instantaneous. Creating a process involves multiple operations—memory allocation, security validation, resource reservation—that take time and may fail. The New state provides a holding area while these operations complete.
You might wonder why we need a separate New state—why not create the process and immediately mark it Ready? The separation exists because: (1) Process creation may fail partway through, and cleanup is easier if the process hasn't been admitted to scheduler queues; (2) Admission control can evaluate whether to accept the process based on system load; (3) The new process may require parent process actions (like setting up pipes) before it can run.
| Characteristic | Description | Implications |
|---|---|---|
| CPU Eligibility | Process cannot receive CPU time | No context switching overhead for New processes |
| Memory Status | Virtual address space being established | Page tables may be incomplete; no physical frames allocated for code/data yet |
| PCB State | Being initialized with process metadata | Not yet linked into scheduler data structures |
| Resource Handles | Being allocated (file descriptors, etc.) | May inherit handles from parent process |
| Duration | Typically very brief (microseconds to milliseconds) | Extended duration indicates resource contention or admission control delay |
Processes don't spontaneously appear—they are explicitly created in response to specific system events. Understanding these triggers reveals the different pathways into the New state and the varying requirements each pathway imposes.
Operating systems textbooks identify four primary events that cause process creation:
Each trigger has distinct characteristics that affect process creation:
System initialization processes are privileged, often running as root/SYSTEM, with access to hardware and kernel services. They're created before user authentication is possible, so security context is established through boot configuration rather than user credentials.
User-requested processes inherit the user's security context, environment variables, and resource limits. The shell typically performs path resolution, argument parsing, and environment setup before invoking the creation syscall.
Process spawning is the most complex case. The child process must decide what to inherit from the parent (open files, environment, working directory) versus what to reset. UNIX's fork-exec model gives the parent explicit control over this inheritance.
Batch jobs operate in controlled environments with predefined resource allocations. The scheduling system may impose quotas, time limits, and priority adjustments not applied to interactive processes.
Every UNIX-like system has a special process with PID 1 (init, systemd, or launchd on macOS). This process is the ancestor of all other processes and bears special responsibilities: it cannot be killed (even by root), it adopts orphaned processes, and its termination causes system shutdown. Understanding that all processes trace their lineage back to init helps conceptualize the process hierarchy.
The Process Control Block (PCB) is the kernel's representation of a process—a data structure containing all information the operating system needs to manage the process. During the New state, the PCB is allocated and populated with initial values.
Most operating systems maintain a pool of pre-allocated PCB structures to accelerate process creation. Allocating a PCB from a pool is O(1), while dynamic allocation might require memory allocator locks and potential page faults.
Key Insight: The PCB is a kernel-space structure. User processes cannot
directly access or modify their own PCB—they can only influence it
indirectly through system calls.
| Field Category | Specific Fields | Initial Value Source |
|---|---|---|
| Process Identity | PID, PPID, Process Group ID, Session ID | Assigned by kernel (PID), inherited from parent (PPID, PGID, SID) |
| Process State | State field set to 'NEW' | Constant value during creation |
| CPU Context | Program Counter, Stack Pointer, General Registers | PC set to program entry point; SP to top of user stack; registers zeroed or inherited |
| Memory Management | Page table pointer, memory limits, segments | Page table allocated; limits from parent or defaults; segments configured for program |
| Scheduling Info | Priority, scheduling class, time slice | Inherited from parent or set to defaults; may be adjusted by nice value |
| File Descriptors | Open file table, current directory, root directory | Typically inherited from parent; FDs 0,1,2 (stdin/stdout/stderr) essential |
| Signal Handling | Signal masks, pending signals, handlers | Handlers inherited; pending signals cleared; masks may be inherited |
| Resource Accounting | CPU time used, memory usage, I/O counts | All counters initialized to zero |
| Security Context | UID, GID, capabilities, SELinux context | Inherited from parent or set based on executable's setuid/setgid bits |
In UNIX systems using fork(), PCB initialization has a unique characteristic: the child's PCB is largely a copy of the parent's PCB. This is why forked children inherit open files, signal handlers, and environment—these are simply copied from the parent's PCB.
However, certain fields are reset rather than copied:
Modern UNIX systems don't actually copy the parent's memory during fork(). Instead, both processes share the same physical pages, marked read-only. Only when either process writes to a page is a copy made. This copy-on-write (COW) optimization makes fork() nearly instantaneous, even for processes with gigabytes of memory.
The Linux task_struct (its PCB equivalent) is approximately 1.5KB in size and references additional allocated structures. Windows' EPROCESS structure is larger still. PCB allocation and initialization is one of the most performance-critical paths in the kernel—it's executed for every process creation. Kernel developers carefully optimize this path, using techniques like slab allocation, lazy initialization, and pre-computed defaults.
While the PCB represents the process to the kernel, the virtual address space represents the process's computational environment. During the New state, this address space is established—though not necessarily populated with physical memory.
A typical process address space contains several segments:
123456789101112131415161718192021
┌─────────────────────────────┐ High Address (e.g., 0x7FFFFFFFFFFF on x64)│ ││ Kernel Space │ ← Not accessible from user mode│ (shared by all procs) ││ │├─────────────────────────────┤│ Stack │ ← Grows downward; local variables, return addresses│ ↓ ││ ││ (unmapped gap) │ ← Guard region between stack and heap│ ││ ↑ ││ Heap │ ← Grows upward; malloc/new allocations│ │├─────────────────────────────┤│ BSS (Uninitialized) │ ← Global variables initialized to zero├─────────────────────────────┤│ Data (Initialized) │ ← Global variables with explicit values├─────────────────────────────┤│ Text (Code) │ ← Executable instructions (read-only)└─────────────────────────────┘ Low Address (e.g., 0x400000 on Linux x64)A crucial optimization: during the New state, the OS typically does not allocate physical memory for the entire address space. Instead, it creates page table entries that are marked "not present." When the process actually accesses a page, a page fault occurs, and only then is physical memory allocated.
This demand paging strategy means:
The page table is the data structure that maps virtual addresses to physical addresses. During New state:
The page table is one of the few structures that must be allocated during New state because the CPU needs it to translate any memory access the process makes.
| Memory Type | Allocated During New? | When Actually Populated? |
|---|---|---|
| Page Table (top level) | Yes | Immediately during creation |
| Code Pages | No (virtual only) | On first instruction fetch (demand paging) |
| Stack Pages | No (virtual only) | On first stack access; may pre-allocate some |
| Heap Pages | No | On first malloc()/brk() call |
| Shared Library Code | No | Mapped from shared cache on first use |
| BSS Segment | No | Zero-page mapped; COW on first write |
For BSS (uninitialized global variables that should be zero), the kernel doesn't allocate unique pages. Instead, all BSS pages initially point to a single, read-only 'zero page.' When the process writes to any BSS location, a page fault occurs, a real page is allocated, zeroed, and mapped in place of the zero page reference. This means a process with 1GB of uninitialized arrays uses almost no physical memory until it actually writes to those arrays.
Beyond memory, a new process requires various system resources. The New state is when these resources are allocated or inherited from the parent process.
In UNIX systems, by default, open file descriptors are inherited across fork():
This inheritance is what makes shell pipelines work. When you type ls | grep foo, the shell:
ls, with stdout redirected to pipe's write endgrep, with stdin redirected to pipe's read endWithout file descriptor inheritance, inter-process communication would require complex setup.
Not all file descriptors should be inherited. Consider a server that opens sensitive configuration files—child processes handling untrusted requests shouldn't have access to these files.
The O_CLOEXEC flag (or fcntl(fd, F_SETFD, FD_CLOEXEC)) marks a file descriptor to be automatically closed when the process calls exec(). This prevents accidental leakage of file descriptors to child programs.
Resource limits constrain what a process can consume:
| Limit | Description | Default (typical) |
|---|---|---|
| RLIMIT_NOFILE | Max open file descriptors | 1024 soft, 1M hard |
| RLIMIT_NPROC | Max processes for user | 4096 |
| RLIMIT_AS | Max virtual address space | Unlimited |
| RLIMIT_STACK | Max stack size | 8MB soft, unlimited hard |
| RLIMIT_CPU | Max CPU time in seconds | Unlimited |
These limits are inherited during process creation and can be reduced (but not increased beyond the hard limit) by unprivileged processes.
One of the most common bugs in systems programming is file descriptor leakage. If a parent process opens many files without O_CLOEXEC and then forks/execs, child processes inherit (and keep open) descriptors they don't need. This wastes kernel resources and can cause security issues or resource exhaustion. Modern practice: always use O_CLOEXEC unless you specifically need descriptor inheritance.
Security context establishment during the New state determines what the process can access throughout its lifetime. This involves user identity, group membership, capabilities, and mandatory access control labels.
Every process carries a security identity consisting of:
Real UID/GID (ruid, rgid): The actual user who owns the process. Used for accounting and signals.
Effective UID/GID (euid, egid): Used for permission checks. Usually equals real UID but differs for setuid programs.
Saved UID/GID (suid, sgid): Preserved copy of euid/egid from before exec(). Allows temporary privilege drop and restoration.
Supplementary Groups: Additional group memberships beyond the primary group.
123456789101112131415161718
// Consider: /usr/bin/passwd owned by root with setuid bit set// User "alice" (uid=1000) executes passwd // Before exec():// ruid=1000, euid=1000, suid=1000 (alice's shell) // During new process creation for passwd:// 1. Kernel sees setuid bit on /usr/bin/passwd// 2. Sets euid = owner of file (root = 0)// 3. Process credentials become:// ruid=1000 (still alice)// euid=0 (root - for permission checks)// suid=0 (saved for potential restoration) // Now passwd can:// - Read/write /etc/shadow (requires root)// - But process remains accountable to alice (ruid=1000)// - Can drop privileges: seteuid(getuid()) sets euid back to 1000Modern Linux has moved beyond simple root/non-root distinction to fine-grained capabilities. Instead of granting all-or-nothing root access, specific capabilities can be granted:
| Capability | Description |
|---|---|
| CAP_NET_BIND_SERVICE | Bind to ports < 1024 |
| CAP_SYS_ADMIN | Various sysadmin operations |
| CAP_NET_RAW | Use raw sockets |
| CAP_CHOWN | Change file ownership |
| CAP_SETUID | Manipulate process UIDs |
During New state, capabilities can be inherited from the parent, granted by file capability attributes, or dropped by the process itself.
Beyond traditional UNIX permissions, systems like SELinux (Linux), AppArmor (Linux), and Sandbox (macOS) impose additional constraints:
unconfined_t, httpd_t). The policy determines what labels can access what resources.These contexts are established during the New state and cannot be elevated later (only further restricted).
Well-designed systems start processes with minimal privileges and grant additional access only when proven necessary. The New state is critical for this: credentials established here persist throughout process lifetime. A process that starts with excessive privileges cannot be meaningfully constrained later—the damage may already be done before constraints are applied.
Not every process that enters the New state successfully transitions to Ready. Admission control is the operating system's mechanism for deciding whether to accept a new process into the system.
Resources are finite. If the system creates processes without limits:
Admission control prevents system collapse by rejecting or delaying process creation when resources are scarce.
kernel.pid_max (Linux) or similar limits cap total processes system-wide. Default is typically 32768; can be increased.1234567891011
# Classic fork bomb - DO NOT RUN THIS# Each invocation creates two children, which each create two more...# Exponential growth exhausts process table in seconds :(){ :|:& };: # Protection mechanisms:# 1. RLIMIT_NPROC - limits processes per user# $ ulimit -u 100 # Limit to 100 processes# 2. cgroups - limits processes per container/group# 3. systemd - can limit processes per serviceWhen admission control rejects a process:
Immediate Failure: The fork()/CreateProcess() call returns an error (EAGAIN, ENOMEM, etc.). The parent process must handle this gracefully.
Delayed Admission: In some real-time systems, new processes may wait in the New state until resources become available. This is less common in general-purpose systems.
Priority-based Admission: The scheduler might admit high-priority processes while rejecting low-priority ones under resource pressure.
Long-term admission (also called job scheduling): Decides which jobs from a batch queue should be initiated. Common in HPC and mainframe environments.
Short-term admission: The immediate decision of whether a fork() should succeed. This is what most developers encounter directly.
In modern systems, long-term admission is often delegated to container orchestrators (Kubernetes) or job schedulers (Slurm) rather than the kernel itself.
Linux's memory overcommit policy affects process creation. With overcommit enabled (default), fork() rarely fails due to memory—the kernel assumes not all allocated memory will be used. With strict overcommit (overcommit_memory=2), the kernel may reject fork() if committed memory would exceed physical RAM plus swap. This is a form of admission control based on memory promises.
Once initialization completes and admission control approves the process, the operating system performs the final transition from New to Ready. This transition is one of the most critical moments in a process's lifecycle—it marks the process as eligible for CPU time.
Depending on the scheduling algorithm, "ready queue" might actually be:
Where the new process is inserted determines when it will run. High-priority processes go to the front; low-priority processes to the back.
If the new process has higher priority than the currently running process, a preemption may occur immediately:
This means a process can transition from New → Ready → Running in rapid succession—potentially running within microseconds of its creation.
The transition from New to Ready completes the process creation lifecycle. The process now has all resources it needs to run: a PCB with initialized state, a virtual address space, inherited resources, and security credentials. It awaits only CPU time—which the scheduler will provide based on its priority, the system's scheduling policy, and competition from other processes.
We've completed a comprehensive exploration of the New state—the first state in a process's lifecycle. Let's consolidate the key concepts:
What's next:
With the New state understood, we move to the Ready state—where processes wait for their turn on the CPU. We'll explore ready queue management, CPU-bound vs I/O-bound process characteristics, and how schedulers select the next process to run.
You now understand the New state comprehensively—from process creation triggers through PCB initialization, memory establishment, resource inheritance, security setup, admission control, and finally transition to the Ready state. This foundation prepares you for understanding how processes compete for and utilize CPU resources in subsequent states.