fork() System Call in C

 Introduction

"fork()" is a system call used in C language to create sub-processes in Linux or Unix systems. Those sub-processes are called "child processes" and the process that creates those sub-processes is called the "parent process". After creating those child processes, those processes are executed concurrently with the parent process. 

Note: After creating those sub-processes, they execute the instructions after the "fork()" statement concurrently with the parent process. Statements that are placed before the "fork()" system call will not execute in the child process


Figure 1.0

The child processes also use the same program counter, registers, and open files that are used in the parent process.

First of all, let's see what is a process.

Process

In simple words, a process is an instance of an executing program. It is considered an active entity since it was created during execution and loaded into RAM. (Random Access Memory). A process will exist for an unlimited span of time as it gets terminated after completion. Also, a process has high resource requirements. (CPU, Memory Address, I/O, ...)

How to create a sub-process

Before looking at the implementation of the fork() system call I would like to say this will not work for Windows operating systems because it doesn't contain this system call API. (Application program interface). So, to run these programs discussed here, it is recommended to use Linux or Unix System, Mac OS, or an online C compiler that supports system calls (ex: Online C Compiler (programiz.com)).

fork() system call contained in the header file called "unistd. h". So, we need to add the relevant header file before using the fork() system call. "unistd.h" is a header file that contains a lot of system call APIs like fork(). pipe() is one of those system call mostly used.

#include <unistd.h>

The signature of the fork() is;

pid_t fork(void);

This signature means that the fork() does not need any arguments as parameters and it will return a process ID to the place that it was called. So, let's see what is meant by the return values of the fork().

Return Values of fork()

Negative value: the creation of the child process was unsuccessful.
Zero: Return to the newly created child process
Positive value: Return to the parent or caller

This means the fork() will return a positive value to the parent process or the caller of the fork() as the process id and return 0 to the child process as the process id. If the return value is a negative value, that means the child process creation was unsuccessful.

Now you have a little idea about what fork() basically does. Let's dive into some examples.

Example 01:

#include <unistd.h>
#include <stdio.h>

int main() {
    fork();
    printf("Hello, world\n");
    return 0;
}

In this example, you can see "Hello, world" is printed two times. This occurs because fork() creates a child process and both the child process and parent process execute the print statement concurrently since it is after the fork().

Let's look what are the return values of the fork() for child processes and parent processes.

Example 02:

#include <unistd.h>
#include <stdio.h>

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // when pid is less than 0
        printf("Error\n");
        return -1;
    }
    if (pid > 0) {
        // when pid is greater than 0
        printf("Parent process - PID %d\n", pid);
        return 0;
    }
    else {
        // when pid is equal to 0
        printf("Child process - PID %d\n", pid);
        return 0;
    }
}



Now you can see fork() will return 0 to its child process and a positive value to its parent process.

Let's see what happens when we use multiple fork() statements in a single program.

Example 03:

#include <unistd.h>
#include <stdio.h>

int main() {
    fork(); // Line 1
    fork(); // Line 2
    fork(); // Line 3
    printf("Hello, world\n");
}

What is the output of this code? Is it 4, 5, or 6 or something? How can we find how many child processes will be created?

First of all, let's have a look at the output;



Here you can see 8 "Hello, world" statements. How can this happen? Let's see.



Explanation: In this case, the parent process (P0) creates a child process (P1) because of fork() in Line 1. After that, P0 and P1 processes execute concurrently from line 2. Line 2 is also a fork() statement and because of line 2 in P0 it creates another child process (P2) and because of line 2 in process P1 it creates another child process (P3). Then P0, P1, P2, and P3 processes execute concurrently from line 3 and there is another fork() statement. Because of line 3 in P0, it creates a child process(P4), because of line 3 in P1, it creates a child process(P6), because of line 3 in P2, it creates a child process(P5), and because of line 3 in P3, it creates a child process(P7). After that, all 8 processes from P0 to P7 print the "Hello, world" on the screen. Therefore, there are 8 print statements.

That's it. What happens if you include a fork() in a loop? 😎 Try it, see the output, and try to understand what happened.

Hope you all are ok with the use of the fork(). 

Thank you..!

Sandares Dhanujaya
Undergraduate,
University of Colombo School of Computing




Comments

Popular Posts