Lab 3- Fork System Call

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 8

Fork System Call

Overview
In an operating system, New processes are created using the fork() system call. It returns a
process ID and does not accept any parameters. A new process (child process) is created by
the fork system call that runs concurrently with the parent process.

What is a Fork System Call in OS?


A new process known as a "child process" is created with the fork system call which runs
concurrently with the process called the parent process. fork system call in OS returns
an integer value and requires no arguments. After the creation of a new child process, both
processes then execute the next command following the fork system call. Therefore, we must
separate the parent from the child by checking the returned value of the fork():

 Negative: A child process could not be successfully created if the fork() returns
a negative value.
 Zero: A new child process is successfully created if the fork() returns a zero.
 Positive: The positive value is the process ID of a child's process to the parent. The
process ID is the type of pid_t that is defined in sys/types.h.

However, the parent and child processes are stored in different memory locations. These
memory spaces contain the same information, therefore any operations carried out by one
process do not affect the other.

A child process uses the same open files, CPU registers, and the same pc(program counter)
used in the parent process.

What is the Use of Fork System Call?


The use of the fork() system call is to create a new process by duplicating the calling process.
The fork() system call is made by the parent process, and if it is successful, a child process is
created.
The fork() system call does not accept any parameters. It simply creates a child process and
returns the process ID. If a fork() call is successful :

 The OS will create two identical copies of the address space for parent and child
processes. Therefore, the address spaces of the parent and child processes are
different.
 A global variable is:
o Created when the process starts
o Declared outside the process
o Lost when the program stops
 A local variable is:
o Created as the process starts
o Declared inside the process
o Lost when the process ends
 The new child process's process ID, or PID, is returned to the parent process. If
something goes wrong, the parent process returns -1.
 Zero is returned to the new child process. (In the case of failure, the child process is
not created).

Syntax for fork() System Call


In Linux and Ubuntu, the fork() system call has the following syntax:

pid_t fork(void);

In the syntax, fork() does not take any arguments, and its returned type is pid_t. Whenever a
child process is successfully created, its PID (Process ID) is returned to the parent process,
and the 0 value is returned to the child process itself.

-1 is returned to the parent process in the case of any errors, and no child process is created.

Examples For fork() System Call


Let’s take a few examples for a better understanding of the fork() system call:

Example 1: Calling fork()

Take a look at the example below, where the fork() system call is used to create a new child
process:

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

//main function begins


int main()
{
fork();
print("the process is created using fork() system call\n");
return 0;
}
// Using fork() system call single time

Output:

the process is created using fork() system call


the process is created using fork() system call

Explanation :

 In this program, We've used the fork() function, which will create a new child
process.
 Once the child process has been created, The child process and the parent process will
both point to the next command.
 In this manner, the remaining commands will be executed 2�2n times,
where n represents the number of fork() system calls.

Consider the following scenario, where fork() is called multiple times:

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

//main function begins


int main()
{
fork();
fork();
fork();
printf("this process is created by fork() system call");
return 0;
}
// fork() is used 3 times:

Output :

// Since the commands will be executed 2n times


// 2^3^ = 8
this process is created by fork() system call
this process is created by fork() system call
this process is created by fork() system call
this process is created by fork() system call
this process is created by fork() system call
this process is created by fork() system call
this process is created by fork() system call
this process is created by fork() system call

Example 2: Testing if fork() was Successful

In the example below, we have checked the integer value returned by fork() using the
decision-making construct.

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

void child() {
printf("Child process is created by fork() system call");
}

void parent() {
printf("parent process is created by fork() system call");
}

//main function begins


int main(void) {
pid_t p = fork();

if(p == 0) {
child();
exit(EXIT_SUCCESS);
}
else if(p > 0) {
wait(NULL);
parent();
}
else {
printf("fork() system call is unable to create child process.");
}

return EXIT_SUCCESS;
}

Output :

Child process is created by fork() system call


parent process is created by fork() system call

Explanation :

 p is the variable of type pid_t which stores the integer value returned by fork().
 When fork() is called and a child is successfully created, the variable p becomes 0.
 while p holds any positive value which is for the parent process as the parent process
will get the child process's id returned.

Example 3: Multiple Child Processes Using fork() and Loop :

In the example below, We used a for loop to create 4 child processes. The PID and PPID
from the child processes were also printed.

// You can also use loop to create as many child processes as you need
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

//main function begins


int main(void) {
for(int i = 1; i <= 4; i++) {
pid_t pid = fork();
if(pid == 0) {
printf("Child process => PPID=%d, PID=%d\n", getppid(), getpid());
exit(0);
}
else {
printf("Parent process => PID=%d\n", getpid());
printf("Waiting for child processes to finish...\n");
wait(NULL);
printf("the child process is finished.\n");
}
}

return EXIT_SUCCESS;
}
// fork() is used 4 times in a for loop

Output :

// we can see, all of the child processes have the same


// parent process ID but have the different child processes
Parent process => PID=554
Waiting for child processes to finish...
Child process => PPID=554, PID=558
The child process is finished.

Parent process => PID=554


Waiting for child processes to finish...
Child process => PPID=554, PID=559
The child process is finished.

Parent process => PID=554


Waiting for child processes to finish...
Child process => PPID=554, PID=560
The child process is finished.

Parent process => PID=554


Waiting for child processes to finish...
Child process => PPID=554, PID=561
The child process is finished.

Explanation :

 Since they all belong to the same parent as we can see, all of the child processes have
the same Parent process ID in the output.

Example 4: Real-Life Example

We've created a 4-digit PIN code in the following example and sent the generated code to the
parent process from a child process.

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

int getPIN() {
srand(getpid() + getppid());
int secret = 1000 + rand() % 9000;
return secret;
}

//main function begins


int main(void) {
int fd[2];
pipe(fd);
pid_t pid = fork();

if(pid > 0) {
close(0);
close(fd[1]);
dup(fd[0]);

int secretNumber;
size_t readBytes = read(fd[0], &secretNumber, sizeof(secretNumber));

printf("Waiting for PIN to be created...\n");


wait(NULL);
printf("Bytes read: %ld\n", readBytes);
printf("PIN: %d\n", secretNumber);
}
else if(pid == 0) {
close(1);
close(fd[0]);
dup(fd[1]);

int secret = getPIN();


write(fd[1], &secret, sizeof(secret));
exit(EXIT_SUCCESS);
}

return EXIT_SUCCESS;
}

Output :

// You can see that every time we run the application


// ,we receive a unique 4-digit PIN code.
Waiting for the PIN to be created...
Bytes read: 4
PIN: 1421

...Program finished with exit code 0


Press ENTER to exit console.

Waiting for PIN to be created...


Bytes read: 4
PIN: 7065

...Program finished with exit code 0


Press ENTER to exit console.

Waiting for PIN to be created...


Bytes read: 4
PIN: 9898
...Program finished with exit code 0
Press ENTER to exit console.

Explanation :

 Instead of doing mathematical computations like md5, sha256, etc. within the main
program's process, the hash can simply be calculated on a child process and returned
to the main process.
 In a child process, a 4-digit PIN code was created and sent to the parent process, the
main application.
 Then, we can print the pin from the main process, as a result, we can see that every
time we run the application, we receive a unique 4-digit PIN code.

FAQs
Q. What do you mean by system call?

A. System calls are unique functions that manage OS operations in kernel mode.

Q. What is kernel mode?

A. Kernel mode is an operating mode for central processing units (CPU).

Q. Which header file defines the "fork()" function?

A. In the header file "unistd.h", fork() is defined.

Q. Which process will execute the statement

A. following the fork() call—the parent or the child? Both the parent and the child processes
are run at the same time, and either of them could get control first from the OS.

Q. What does the fork() function's negative value denote?

A. It denotes that the creation of the child process was unsuccessful.

Q. What are the differences between the exec() and fork() functions?

A.

fork() exec()
The fork() creates a new process that is an The exec() creates a new process in place
identical copy of the original process. of the original process.
Both the parent and the child processes are Unless there is an error, control never
run at the same time. goes back to the original process.
Parent and child processes are in different parent address space is replaced by the
address spaces. child address space.
Conclusion
 A new process known as a “child process” is created with the fork system call which
runs concurrently with the process called the parent process.
 The parent process and the child process must be separated by checking the returned
value of the fork().
 A child process uses the same CPU registers, the same open files, and the
same pc(program counter) used in the parent process.
 In the syntax, fork() does not take any arguments, and its returned type is pid_t.
 The commands will be executed 2n times, which is the total number of processes,
where n represents the number of fork() system calls.
 In real-life, we can create some unique codes with the fork() system call as every
child process will give a unique value.

You might also like