Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Fork (system call)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{DISPLAYTITLE:fork (system call)}} {{short description|In computing, an operation whereby a process creates a copy of itself}} In [[computing]], particularly in the context of the [[Unix]] operating system and [[Unix-like|its workalikes]], '''fork''' is an operation whereby a [[Computer process|process]] creates a copy of itself. It is an interface which is required for compliance with the [[POSIX]] and [[Single UNIX Specification]] standards. It is usually implemented as a [[C standard library]] [[Wrapper library|wrapper]] to the fork, clone, or other [[system call]]s of the [[kernel (operating system)|kernel]]. Fork is the primary method of process creation on Unix-like operating systems. == Overview == In multitasking operating systems, processes (running programs) need a way to create new processes, e.g. to run other programs. Fork and its variants are typically the only way of doing so in Unix-like systems. For a process to start the execution of a different program, it first forks to create a copy of itself. Then, the copy, called the "[[child process]]", makes any environment changes the child will need and then calls the [[exec (system call)|exec]] system call to overlay itself with the new program: it ceases execution of its former program in favor of the new. (Or, in rarer cases, the child forgoes the [[exec (system call)|exec]] and continues executing, as a separate process, some other functionality of the original program.) The fork operation creates a separate [[address space]] for the child. The child process has an exact copy of all the memory segments of the parent process. In modern UNIX variants that follow the [[virtual memory]] model from [[SunOS]]-4.0, [[copy-on-write]] semantics are implemented and the physical memory need not be actually copied. Instead, [[virtual memory pages]] in both processes may refer to the same pages of [[physical memory]] until one of them writes to such a page: then it is copied. This optimization is important in the common case where fork is used in conjunction with exec to execute a new program: typically, the child process performs only a small set of actions before it ceases execution of its program in favour of the program to be started, and it requires very few, if any, of its parent's [[data structure]]s. When a process calls fork, it is deemed the [[parent process]] and the newly created process is its child. After the fork, both processes not only run the same program, but they resume execution as though both had called the system call. They can then inspect the call's [[return value]] to determine their status, child or parent, and act accordingly. == History == One of the earliest references to a fork concept appeared in ''A Multiprocessor System Design'' by [[Melvin Conway]], published in 1962.<ref>{{Cite journal|title=Notes on the History of Fork and Join|last=Nyman|first=Linus|date=25 August 2016|journal=IEEE Annals of the History of Computing|volume=38|issue=3|pages=84–87|doi=10.1109/MAHC.2016.34}}</ref> Conway's paper motivated the implementation by [[L. Peter Deutsch]] of fork in the [[Project Genie|GENIE time-sharing system]], where the concept was borrowed by [[Ken Thompson]] for its earliest appearance<ref>{{Cite web|url=https://github.com/dspinellis/unix-history-repo/blob/Research-PDP7-Snapshot-Development/s3.s#L43-L70|title=s3.s from Research UNIX|date=1970|website=GitHub}}</ref> in [[Research Unix]].<ref>{{cite encyclopedia|title=SYS FORK (II)|encyclopedia=UNIX Programmer's Manual|publisher=[[Bell Labs|Bell Laboratories]]|url=https://www.bell-labs.com/usr/dmr/www/pdfs/man21.pdf|date=3 November 1971|author=[[Ken Thompson]] and [[Dennis Ritchie]]}}</ref><ref name="Ritchie">{{cite journal|last1=Ritchie|first1=Dennis M.|last2=Thompson|first2=Ken|date=July 1978|title=The UNIX Time-Sharing System|url=https://www.bell-labs.com/usr/dmr/www/cacm.pdf|journal=Bell System Tech. J.|publisher=AT&T|volume=57|issue=6|pages=1905–1929|doi=10.1002/j.1538-7305.1978.tb02136.x|access-date=22 April 2014|authorlink1=Dennis Ritchie}}</ref> Fork later became a standard interface in [[POSIX]].<ref name="posix">{{man|sh|fork}}</ref> ==Communication== The child process starts off with a copy of its parent's [[file descriptor]]s.{{r|posix}} For interprocess communication, the parent process will often create one or several [[Pipe (computer science)|pipe]]s, and then after forking the processes will close the ends of the pipes that they do not need.<ref>{{man|sh|pipe}}</ref> ==Variants== ===Vfork=== Vfork is a variant of fork with the same [[calling convention]] and much the same semantics, but only to be used in restricted situations. It originated in the [[Berkeley Software Distribution|3BSD]] version of Unix,<ref name="man|2|vfork|Linux">{{man|2|vfork|Linux}}</ref>{{r|netbsd-vfork}}<ref>{{cite encyclopedia |title=vfork(2) |encyclopedia=UNIX Programmer's Manual, Virtual VAX-11 Version |publisher=University of California, Berkeley |date=December 1979}}</ref> the first Unix to support virtual memory. It was standardized by POSIX, which permitted vfork to have exactly the same behavior as fork, but was marked obsolescent in the 2004 edition<ref name="posix-vfork">{{man|sh|vfork|SUS6}}</ref> and was replaced by [[Spawn (computing)#POSIX spawn functions|posix_spawn]]() (which is typically implemented via vfork) in subsequent editions. When a vfork system call is issued, the parent process will be suspended until the child process has either completed execution or been replaced with a new executable image via one of the "[[Exec (system call)|exec]]" family of system calls. The child borrows the [[memory management unit]] setup from the parent and memory pages are shared among the parent and child process with no copying done, and in particular with no [[copy-on-write]] semantics;<ref name="posix-vfork"/> hence, if the child process makes a modification in any of the shared pages, no new page will be created and the modified pages are visible to the parent process too. Since there is absolutely no page copying involved (consuming additional memory), this technique is an optimization over plain fork in full-copy environments when used with exec. In POSIX, using vfork for any purpose except as a prelude to an immediate call to a function from the exec family (and a select few other operations) gives rise to [[undefined behavior]].<ref name="posix-vfork"/> As with vfork, the child borrows data structures rather than copying them. vfork is still faster than a fork that uses copy on write semantics. [[UNIX System V|System V]] did not support this function call before System VR4 was introduced,{{citation needed|date=May 2015}} because the memory sharing that it causes is error-prone: {{quote|''Vfork'' does not copy page tables so it is faster than the System V ''fork'' implementation. But the child process executes in the same physical address space as the parent process (until an ''exec'' or ''exit'') and can thus overwrite the parent's data and stack. A dangerous situation could arise if a programmer uses ''vfork'' incorrectly, so the onus for calling ''vfork'' lies with the programmer. The difference between the System V approach and the BSD approach is philosophical: Should the kernel hide idiosyncrasies of its implementation from users, or should it allow sophisticated users the opportunity to take advantage of the implementation to do a logical function more efficiently?|Maurice J. Bach<ref>{{Cite book |title=The Design of The UNIX Operating System |first=Maurice J. |last=Bach |publisher=Prentice–Hall |year=1986 |pages=291–292|bibcode=1986duos.book.....B }}</ref>}} Similarly, the Linux [[man page]] for vfork strongly discourages its use:<ref name="man|2|vfork|Linux"/>{{Failed verification|date=November 2019|reason=quote not in source|talk=unfortunate, etc}} {{quote|It is rather unfortunate that Linux revived this specter from the past. The BSD man page states: "This system call will be eliminated when proper system sharing mechanisms are implemented. Users should not depend on the memory sharing semantics of vfork() as it will, in that case, be made synonymous to fork(2)."}} Other problems with {{mono|vfork}} include [[Deadlock (computer science)|deadlock]]s that might occur in [[multi-threaded|multithreaded]] programs due to interactions with [[dynamic linking]].{{r|oracle}} As a replacement for the {{mono|vfork}} interface, POSIX introduced the {{mono|posix_spawn}} family of functions that combine the actions of fork and exec. These functions may be implemented as library routines in terms of {{mono|fork}}, as is done in Linux,{{r|oracle}} or in terms of {{mono|vfork}} for better performance, as is done in Solaris,<ref name="oracle">{{cite web |last=Nakhimovsky |first=Greg |date=May 2006 |title=Minimizing Memory Usage for Creating Application Subprocesses |url=http://www.oracle.com/technetwork/server-storage/solaris10/subprocess-136439.html |archive-url=https://web.archive.org/web/20190922113430/https://www.oracle.com/technetwork/server-storage/solaris10/subprocess-136439.html |archive-date=Sep 22, 2019 |website=Oracle Technology Network |publisher=[[Oracle Corporation]]}}</ref><ref>[[sourceforge:p/schillix-on/schillix-on/ci/default/tree/usr/src/lib/libc/port/threads/spawn.c|The OpenSolaris posix_spawn() implementation]]</ref> but the POSIX specification notes that they were "designed as [[system call|kernel operations]]", especially for operating systems running on constrained hardware and [[Real-time computing|real-time systems]].<ref>{{man|sh|posix_spawn|SUS}}</ref> While the 4.4BSD implementation got rid of the vfork implementation, causing vfork to have the same behavior as fork, it was later reinstated in the [[NetBSD]] operating system for performance reasons.<ref name="netbsd-vfork">{{cite web |title=NetBSD Documentation: Why implement traditional vfork() |website=NetBSD Project |access-date=16 October 2013 |url=http://www.netbsd.org/docs/kernel/vfork.html}}</ref> Some embedded operating systems such as [[uClinux]] omit fork and only implement vfork, because they need to operate on devices where copy-on-write is impossible to implement due to lack of a memory management unit. ===Rfork=== The [[Plan 9 from Bell Labs|Plan 9]] operating system, created by the designers of Unix, includes fork but also a variant called "rfork" that permits fine-grained sharing of resources between parent and child processes, including the address space (except for a [[Call stack|stack]] segment, which is unique to each process), [[environment variable]]s and the filesystem namespace;<ref>{{man|2|fork|Plan 9}}</ref> this makes it a unified interface for the creation of both processes and [[Thread (computer science)|threads]] within them.<ref>{{man|2|intro|Plan 9}}</ref> Both [[FreeBSD]]<ref>{{man|2|rfork|FreeBSD}}</ref> and [[IRIX]] adopted the rfork system call from Plan 9, the latter renaming it "sproc".{{r|opensources}} {{anchor|Linux_clone_syscall}} ===Clone=== <code>clone</code> is a system call in the [[Linux kernel]] that creates a child process that may share parts of its execution [[context (computing)|context]] with the parent. Like FreeBSD's rfork and IRIX's sproc, Linux's clone was inspired by Plan 9's rfork and can be used to implement threads (though application programmers will typically use a higher-level interface such as [[pthreads]], implemented on top of clone). The "separate stacks" feature from Plan 9 and IRIX has been omitted because (according to [[Linus Torvalds]]) it causes too much overhead.<ref name="opensources">{{cite encyclopedia |title=The Linux edge |first=Linus |last=Torvalds |encyclopedia=Open Sources: Voices from the Open Source Revolution |year=1999 |publisher=O'Reilly |url=https://archive.org/details/isbn_9781565925823 |isbn=978-1-56592-582-3 |url-access=registration }}</ref> ==Forking in other operating systems== {{one source|section|date= February 2015}} In the original design of the [[OpenVMS|VMS]] operating system (1977), a copy operation with subsequent mutation of the content of a few specific addresses for the new process as in forking was considered risky.{{citation needed|date=October 2013}} Errors in the current process state may be copied to a child process. Here, the metaphor of process spawning is used: each component of the memory layout of the new process is newly constructed from scratch. The [[spawn (computing)|spawn]] metaphor was later adopted in Microsoft operating systems (1993). The POSIX-compatibility component of [[VM/CMS]] (OpenExtensions) provides a very limited implementation of fork, in which the parent is suspended while the child executes, and the child and the parent share the same address space.<ref>{{cite web|url=http://www-01.ibm.com/support/knowledgecenter/SSB27U_6.2.0/com.ibm.zvm.v620.dmsp0/hcsp0c0022.htm%23wq47?lang=en|title=z/VM > z/VM 6.2.0 > Application Programming > z/VM V6R2 OpenExtensions POSIX Conformance Document > POSIX.1 Conformance Document > Section 3. Process Primitives > 3.1 Process Creation and Execution > 3.1.1 Process Creation |publisher=IBM|access-date=April 21, 2015}}</ref> This is essentially a ''vfork'' labelled as a ''fork''. (This applies to the CMS guest operating system only; other VM guest operating systems, such as Linux, provide standard fork functionality.) ==Application usage== The following variant of the [["Hello, World!" program]] demonstrates the mechanics of the {{mono|fork}} system call in the [[C (programming language)|C]] programming language. The program forks into two processes, each deciding what functionality they perform based on the return value of the fork system call. [[Boilerplate code]] such as [[Header file|header inclusions]] has been omitted. <syntaxhighlight lang="c"> int main(void) { pid_t pid = fork(); if (pid == -1) { perror("fork failed"); exit(EXIT_FAILURE); } else if (pid == 0) { printf("Hello from the child process!\n"); _exit(EXIT_SUCCESS); } else { int status; (void)waitpid(pid, &status, 0); } return EXIT_SUCCESS; } </syntaxhighlight> What follows is a dissection of this program. <syntaxhighlight lang="c"> pid_t pid = fork(); </syntaxhighlight> The first statement in {{mono|main}} calls the {{mono|fork}} system call to split execution into two processes. The return value of {{mono|fork}} is recorded in a variable of type {{mono|pid_t}}, which is the POSIX type for process identifiers (PIDs). <syntaxhighlight lang="c"> if (pid == -1) { perror("fork failed"); exit(EXIT_FAILURE); } </syntaxhighlight> Minus one indicates an error in {{mono|fork}}: no new process was created, so an error message is printed. If {{mono|fork}} was successful, then there are now two processes, both executing the {{mono|main}} function from the point where {{mono|fork}} has returned. To make the processes perform different tasks, the program must [[Branch (computer science)|branch]] on the return value of {{mono|fork}} to determine whether it is executing as the ''child'' process or the ''parent'' process. <syntaxhighlight lang="c"> else if (pid == 0) { printf("Hello from the child process!\n"); _exit(EXIT_SUCCESS); } </syntaxhighlight> In the child process, the return value appears as zero (which is an invalid [[process identifier]]). The child process prints the desired greeting message, then exits. (For technical reasons, the POSIX {{mono|_exit}} function must be used here instead of the C standard {{mono|exit}} function.) <syntaxhighlight lang="c"> else { int status; (void)waitpid(pid, &status, 0); } </syntaxhighlight> The other process, the parent, receives from {{mono|fork}} the process identifier of the child, which is always a positive number. The parent process passes this identifier to the {{mono|waitpid}} system call to suspend execution until the child has exited. When this has happened, the parent resumes execution and exits by means of the {{mono|return}} statement. ==See also== *[[Fork bomb]] *[[Fork–exec]] *[[exit (system call)]] *[[spawn (computing)]] *[[wait (system call)]] ==References== {{Reflist|30em}} [[Category:Process (computing)]] [[Category:C POSIX library]] [[Category:Articles with example C code]] [[Category:System calls]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:Anchor
(
edit
)
Template:Citation needed
(
edit
)
Template:Cite encyclopedia
(
edit
)
Template:Cite journal
(
edit
)
Template:Cite web
(
edit
)
Template:Failed verification
(
edit
)
Template:Man
(
edit
)
Template:Mono
(
edit
)
Template:One source
(
edit
)
Template:Quote
(
edit
)
Template:R
(
edit
)
Template:Reflist
(
edit
)
Template:Short description
(
edit
)