Google Ads

June 29, 2015

Linux C/C++ fork () Example

If you ever wanted to do multiple tasks at the same time in your C/C++ program then Linux fork () system call function is for you. When your C/C++ compiled binary program begins execution, it creates a main process in which all the program instructions are executed. In Linux every program you run will create one or more processes. Inside each process the program instructions will be executed sequentially. Which means inside one process without completing one task the program will not be able to do another task and that is where fork () function comes in handy. The fork () function will let you create a new process which is a exact copy of the main process but completely independent and run alongside the main process. For example, if you are copying a file in the main process then the new process created by fork () can be used to update the user interface for the copy operation. 

Things to remember about processes are:
 

  • Processes are one of the building blocks for multitasking in Linux
  • Each process has it's own unique id provided by the Linux kernel by which the process can be tracked for different purposes
  • Processes can run independently to each other, therefore closing or terminating one process does not effect the other processes
  • Any process will have their own memory space, therefore variables from stack and heap from one process are not accessible by other processes
   
   
Now, lets build a simple C program to see how fork () can be utilized


In the program we call the main process as parent process    , and the new process created from inside main process as child process. This naming convention for processes is very typical, since one process can create another new process by using fork().

We build a simple program where, parent process counts to 10 while at the same time child process counts to 20. After finishing counting the parent process waits for the child process to end.

Code:


#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main (int argc, char *argv[])
{
    pid_t child_id;
   
    child_id = fork ();
   
    if (child_id == -1) {
        printf ("Creating new process by fork() failed!\n");
        return 1;
    }
    else if (child_id == 0) {
        /* code block for child process */
        int count;
        for (count = 1; count < 10; count++) {
            printf ("Child counting: %d\n", count);
            sleep (1);
        }
        _exit (0);
    }
    else {
        /* code block for parent process */
        int child_exit_status;
        int count;
        printf ("Child process id: %d\n", child_id);
        for (count = 1; count < 5; count++) {
            printf ("Parent counting: %d\n", count);
            sleep (1);
        }
        printf ("Waiting for child to end\n");
        wait (&child_exit_status);
        printf ("Child exited with %d\n", child_exit_status);
    }

    return EXIT_SUCCESS;
}

The above code should print the following output in the terminal:
Child process id: 7225
Child counting: 1
Parent counting: 1
Parent counting: 2
Child counting: 2
Child counting: 3
Parent counting: 3
Child counting: 4
Parent counting: 4
Child counting: 5
Waiting for child to end
Child counting: 6
Child counting: 7
Child counting: 8
Child counting: 9
Child exited with 0


Now, let's go through the most important elements in the code:

We need to include unistd.h for the fork function. The other two header files types.h and wait.h are required by the wait () function. First, we create a variable of type pid_t for storing child process id which will be returned by the fork () function. The fork function returns -1 if the function can not create a new process and if successful fork() returns 0 to the child process and the process id of created process (child) to the parent process (main process). Therefore, inside the child process the value for child_id would be 0 and it would be child process id inside parent (main) process. Inside the child process block the _exit function is used to terminate the child process. The sleep function inside the for loop blocks will suspend the respective execution for specified amount of seconds given in the parameters, in our case it is one second. And finally the wait function will suspend the parent (main) process until state of one of the child processes changes, in our case when the child process exits. And finally, the exit status of the child process is retrieved by using the wait function which is stored in the child_exit_status variable.

Hopefully, this tutorial helped you learn basic about processes.
 

Download the fork() example source file and test it by yourself:
fork.c

No comments:

Post a Comment