Till now we know that whenever we execute a program then a process is created and would be terminated after the completion of the execution. What if we need to create a process within the program and may be wanted to schedule a different task for it. Can this be achieved? Yes, obviously through process creation. Of course, after the job is done it would get terminated automatically or you can terminate it as needed.
Process creation is achieved through the fork() system call. The newly created process is called the child process and the process that initiated it (or the process when execution is started) is called the parent process. After the fork() system call, now we have two processes - parent and child processes. How to differentiate them? Very simple, it is through their return values.
After creation of the child process, let us see the fork() system call details.
#include <sys/types.h> #include <unistd.h> pid_t fork(void);
Creates the child process. After this call, there are two processes, the existing one is called the parent process and the newly created one is called the child process.
The fork() system call returns either of the three values −
Negative value to indicate an error, i.e., unsuccessful in creating the child process.
Returns a zero for child process.
Returns a positive value for the parent process. This value is the process ID of the newly created child process.
Let us consider a simple program.
File name: basicfork.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { fork(); printf("Called fork() system call\n"); return 0; }
gcc basicfork.c -o basicfork
Called fork() system call Called fork() system call
Note − Usually after fork() call, the child process and the parent process would perform different tasks. If the same task needs to be run, then for each fork() call it would run 2 power n times, where n is the number of times fork() is invoked.
In the above case, fork() is called once, hence the output is printed twice (2 power 1). If fork() is called, say 3 times, then the output would be printed 8 times (2 power 3). If it is called 5 times, then it prints 32 times and so on and so forth.
Having seen fork() create the child process, it is time to see the details of the parent and the child processes.
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { pid_t pid, mypid, myppid; pid = getpid(); printf("Before fork: Process id is %d\n", pid); pid = fork(); if (pid < 0) { perror("fork() failure\n"); return 1; } // Child process if (pid == 0) { printf("This is child process\n"); mypid = getpid(); myppid = getppid(); printf("Process id is %d and PPID is %d\n", mypid, myppid); } else { // Parent process sleep(2); printf("This is parent process\n"); mypid = getpid(); myppid = getppid(); printf("Process id is %d and PPID is %d\n", mypid, myppid); printf("Newly created process id or child pid is %d\n", pid); } return 0; }
Before fork: Process id is 166629 This is child process Process id is 166630 and PPID is 166629 Before fork: Process id is 166629 This is parent process Process id is 166629 and PPID is 166628 Newly created process id or child pid is 166630
A process can terminate in either of the two ways −
Abnormally, occurs on delivery of certain signals, say terminate signal.
Normally, using _exit() system call (or _Exit() system call) or exit() library function.
The difference between _exit() and exit() is mainly the cleanup activity. The exit() does some cleanup before returning the control back to the kernel, while the _exit() (or _Exit()) would return the control back to the kernel immediately.
Consider the following example program with exit().
#include <stdio.h> #include <stdlib.h> void exitfunc() { printf("Called cleanup function - exitfunc()\n"); return; } int main() { atexit(exitfunc); printf("Hello, World!\n"); exit (0); }
Hello, World! Called cleanup function - exitfunc()
Consider the following example program with _exit().
#include <stdio.h> #include <unistd.h> void exitfunc() { printf("Called cleanup function - exitfunc()\n"); return; } int main() { atexit(exitfunc); printf("Hello, World!\n"); _exit (0); }
Hello, World!