Problem: how can I create multiple processes? The answer in the Unix world has always been: fork off.
Note that although the child process has an exact copy of all variables, it is a copy, so any changes in the child process its variables do not affect the original (parent) process its variables.
One application which nowadays immediately jumps to mind is the webserver, which forks off a child process for every connection.
#include <stdlib.h> #include <unistd.h> main() { int n_return_value; /* to check fork() return value */ char* psz_args[2]; /* the arguments to pass to execv() */ printf("Forking process\n"); n_return_value=fork(); if(n_return_value < 0) /* check for error code */ { printf("Cannot fork!\n"); exit(1); } /* After this comment, two copies exist of the same program. The only * difference between the copies is that they receive a different * result of the fork() call */ if(n_return_value == 0) /* the child copy of the program receives 0 as the result of fork */ { printf("Child process pid is %d and return value is %d\n", getpid(), n_return_value); } else /* the parent copy of the program receives the process id of the child from fork */ { printf("Parent process pid is %d and return value is %d\n", getpid(), n_return_value); } pzs_args[0] = "-l"; /* this is the first argument */ pzs_args[1] = NULL; /* the list of arguments must be closed by a character pointer to NULL */ execv("/bin/ls", pzs_args); printf("This line will never be printed, because the previous instruction execv() replaces the process image!"); return 0; }
Fork is also used to "fork into the background"; i.e. the process is started, forks and lets the parent end. This way, the process continues in the background as a server process.
Nowadays, it's more common not to fork into the background. It makes debugging and in general, managing the process harder. Instead, a script or separate executable is offered that starts the software and puts it in the background.
Also, since forking is a relatively heavy call, it's not really suitable for forking on request. Rather, instances are preforked so as not to overload the machine when instances are suddenly needed.
From the GNU manual: "Another way to provide a service on an Internet port is to let the daemon program inetd do the listening. inetd is a program that runs all the time and waits (using select) for messages on a specified set of ports. When it receives a message, it accepts the connection (if the socket style calls for connections) and then forks a child process to run the corresponding server program. You specify the ports and their programs in the file /etc/inetd.conf."
You can also use the Linux-specific clone() call, which unlike fork(), shares the complete memory space of the parent. This call is also used for implementing threading libraries. Example below by Tiemen Schut:
#include <stdio.h> #include <sched.h> #include <stdlib.h> int clone_f (void); int a = 0, b = 0; int main (int argc, char **argv) { void *child_stack = malloc (8192) + 8192; printf ("main: cloning ... \n"); clone ((void *)clone_f, child_stack, CLONE_VM, NULL); while (a == 0); if (a == 1) { printf ("clone changed a in 1 :o\n"); } return 0; } int clone_f (void) { printf ("clone: hello\n"); a = 1; usleep (1000000); //while (1); return 0; }