fork(2)
System call
Duplicates the calling process. The child gets a copy of the memory and of the open descriptors, and the return value tells which one is which.
#include <unistd.h>
pid_t fork(void);Description
fork creates a new process, the child, by copying the one that calls it, the parent. When the call returns, both run the rest of the same program. The child has its own PID, and its parent is the process that called fork.
Memory is copied: variables, stack, heap, and also the printf buffers that have not been flushed yet. Linux only really copies a page when one of the two processes modifies it (copy-on-write), which keeps the call fast. File descriptors are duplicated too, but each one refers to the same open file as in the parent, with the same read or write offset: that is what lets a parent and a child share a pipe.
Return value
fork returns twice, once in each process:
| Value | In which process |
|---|---|
0 | the child |
| the child's PID, positive | the parent |
-1 | the parent alone: no child was created, and errno says why |
The usual causes of failure are EAGAIN (the process limit was reached) and ENOMEM (not enough kernel memory).
Pitfalls
Nothing guarantees whether the parent or the child runs first. A program that depends on an order has to synchronize, with
waitpidor a pipe.A
printfcalled beforeforkcan show up twice when output goes to a pipe or a file: the unflushed buffer is copied into the child. Callfflush(stdout)right beforefork.A child that has finished stays a zombie until the parent waits for it with
waitorwaitpid.In a loop, forgetting to leave the child (with
exitor areturn) means the child keeps looping and creates processes of its own.
Example
#include <stdio.h>#include <sys/wait.h>#include <unistd.h>
int main(void){ int x = 1; pid_t pid = fork();
if (pid == -1) { perror("fork"); return 1; } if (pid == 0) { x = 42; printf("child: x = %d\n", x); return 0; } waitpid(pid, NULL, 0); printf("parent: x = %d\n", x); return 0;}$ gcc -Wall -Wextra copy.c -o copy$ ./copychild: x = 42parent: x = 1The child modifies its copy of x; the parent's copy has not moved. The parent waits for the child before printing, which fixes the order of the two lines.
process_stream_open
Write process_stream_open, which forks a child to run a command with execvp and hands the parent one end of a pipe, without waiting for the child.