fork(2)
๐ NAME ๐
fork โ create a child process ๐
so like, quick intro bestie: this whole page is the manual for fork(2), and it lives in the System Calls Manual. it's giving "the origin story of every process you've ever met" โจ
๐ LIBRARY ๐
Standard C library (libc, -lc) ๐ซถ
โจ SYNOPSIS โจ
#include <unistd.h>
pid_t fork(void);
๐ DESCRIPTION ๐
so fork() creates a whole new process by duplicating the process that called it. the new baby one is called the child process ๐ฑ and the one that did the calling is the parent process. it's giving single parent, no cap.
the child and the parent run in separate memory spaces. at the exact moment of the fork(), both memory spaces hold the same content. and like โ memory writes, file mappings (mmap(2)), and unmappings (munmap(2)) done by one of them do not affect the other. they're independent, periodt.
the child is an exact duplicate of the parent except for these little differences, and bestie, some of these are lowkey important:
- the child has its own unique process ID, and this PID does not match the ID of any existing process group (
setpgid(2)) or session. - the child's parent process ID is the same as the parent's process ID. (iconic, actually)
- the child does not inherit its parent's memory locks (
mlock(2),mlockall(2)). - process resource utilizations (
getrusage(2)) and CPU time counters (times(2)) get reset to zero in the child. fresh start, we love that. - the child's set of pending signals starts out empty (
sigpending(2)). - the child does not inherit semaphore adjustments from its parent (
semop(2)). - the child does not inherit process-associated record locks from its parent (
fcntl(2)). (but hear me out โ it does inheritfcntl(2)open file description locks andflock(2)locks from its parent. iykyk ๐) - the child does not inherit timers from its parent (
setitimer(2),alarm(2),timer_create(2)). - the child does not inherit outstanding asynchronous I/O operations from its parent (
aio_read(3),aio_write(3)), and it also doesn't inherit any asynchronous I/O contexts from its parent (seeio_setup(2)).
all those attributes up there โ๏ธ are specified in POSIX.1. but wait, there's more โ parent and child also differ on these Linux-specific process attributes:
- the child does not inherit directory change notifications (dnotify) from its parent (see the description of
F_NOTIFYinfcntl(2)). - the
prctl(2)PR_SET_PDEATHSIGsetting gets reset, so the child does not receive a signal when its parent terminates. ๐ฅฒ - the default timer slack value is set to the parent's current timer slack value. see the description of
PR_SET_TIMERSLACKinprctl(2). - memory mappings that have been marked with the
madvise(2)MADV_DONTFORKflag are not inherited across afork(). - memory in address ranges marked with the
madvise(2)MADV_WIPEONFORKflag gets zeroed in the child after afork(). (and theMADV_WIPEONFORKsetting itself stays in place for those address ranges in the child.) - the termination signal of the child is always
SIGCHLD(seeclone(2)). - the port access permission bits set by
ioperm(2)are not inherited by the child โ the child has to turn on any bits it needs usingioperm(2)itself.
and there's even more, so stay with me:
- the child process is created with a single thread โ the one that called
fork(). the entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects. usingpthread_atfork(3)may be helpful for dealing with any problems this can cause. (this is the part where things get spicy ๐) - after a
fork()in a multithreaded program, the child can safely call only async-signal-safe functions (seesignal-safety(7)) until the moment it callsexecve(2). - the child inherits copies of the parent's set of open file descriptors. each file descriptor in the child refers to the same open file description (see
open(2)) as the corresponding file descriptor in the parent. meaning: the two fds share open file status flags, file offset, and signal-driven I/O attributes (see the description ofF_SETOWNandF_SETSIGinfcntl(2)). - the child inherits copies of the parent's set of open message queue descriptors (see
mq_overview(7)). each file descriptor in the child refers to the same open message queue description as the corresponding fd in the parent โ so the two share the same flags (mq_flags). - the child inherits copies of the parent's set of open directory streams (see
opendir(3)).POSIX.1says the corresponding directory streams in parent and child may share the directory stream positioning โ but on Linux/glibc they do not. slay ๐
๐ซถ RETURN VALUE ๐ซถ
on success, the PID of the child process is returned in the parent, and 0 is returned in the child. yes bestie, that's the whole trick โ you check the return value and that's how you know which one you are โจ
on failure, -1 is returned in the parent, no child process is created, and errno is set to tell you what went wrong.
๐ญ ERRORS ๐ญ
EAGAINโ a system-imposed limit on the number of threads was hit. there are a few different limits that can trigger this one:- the
RLIMIT_NPROCsoft resource limit (set viasetrlimit(2)), which limits the number of processes and threads for a real user ID, was reached; - the kernel's system-wide limit on the number of processes and threads,
/proc/sys/kernel/threads-max, was reached (seeproc(5)); - the maximum number of PIDs,
/proc/sys/kernel/pid_max, was reached (seeproc(5)); or - the PID limit (
pids.max) imposed by the cgroup "process number" (PIDs) controller was reached.
- the
EAGAINโ the caller is operating under theSCHED_DEADLINEscheduling policy and does not have the reset-on-fork flag set. seesched(7).ENOMEMโfork()failed to allocate the necessary kernel structures because memory is tight.ENOMEMโ an attempt was made to create a child process in a PID namespace whose "init" process has terminated. seepid_namespaces(7).ENOSYSโfork()is not supported on this platform (for example, hardware without a Memory-Management Unit).ERESTARTNOINTR(since Linux 2.6.17) โ system call was interrupted by a signal and will be restarted. (this one can only be seen during a trace ๐)
๐ VERSIONS ๐
๐ง C library/kernel differences ๐ง
since glibc 2.3.3, instead of invoking the kernel's fork() system call, the glibc fork() wrapper โ provided as part of the NPTL threading implementation โ invokes clone(2) with flags that give the same effect as the traditional system call. (a call to fork() is equivalent to a call to clone(2) specifying flags as just SIGCHLD.) and the glibc wrapper also invokes any fork handlers that have been established using pthread_atfork(3).
๐ฆ Async-signal safety ๐ฆ
_Fork(3) is an async-signal safe variant of fork(2).
๐ STANDARDS ๐
POSIX.1-2024.
๐ HISTORY ๐
4.3BSD, SVr4, POSIX.1-1988.
๐ NOTES ๐
under Linux, fork() is implemented using copy-on-write pages, so the only penalty it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child. the way that it's literally so efficient... obsessed ๐
๐ธ EXAMPLES ๐ธ
see pipe(2) and wait(2) for more examples.
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
pid_t pid;
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
perror("signal");
exit(EXIT_FAILURE);
}
pid = fork();
switch (pid) {
case -1:
perror("fork");
exit(EXIT_FAILURE);
case 0:
puts("Child exiting.");
fflush(stdout);
_exit(EXIT_SUCCESS);
default:
printf("Child is PID %jd\n", (intmax_t) pid);
puts("Parent exiting.");
exit(EXIT_SUCCESS);
}
}
๐ SEE ALSO ๐
clone(2), execve(2), exit(2), _exit(3), setrlimit(2), unshare(2), vfork(2), wait(2), daemon(3), _Fork(3), pthread_atfork(3), capabilities(7), credentials(7)
okay bestie that's the whole page, and ngl you ate that ๐ซถ this was Linux man-pages 6.20, dated 2026-06-05, and the page itself is, you guessed it, fork(2). go forth and fork responsibly, mwah ๐โจ๐
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 2006, Michael Kerrisk <mtk.manpages@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms