Fork System Call in C

29/12/2020
Chưa phân loại
fork() system call is used to create child processes in a C program. fork() is used where parallel processing is required in your application. The fork() system function is defined in the headers sys/types.h and unistd.h. In a program where you use fork, you also have to use wait() system call. wait() system call is used to wait in the parent process for the child process to finish. To finish a child process, the exit() system call is used in the child process. The wait() function is defined in the header sys/wait.h and the exit() function is defined in the header stdlib.h.

Fig 1: Basic fork() workflow

In this article, I am going to show you how to use fork() system call to create child processes in C. So, let’s get started.

fork() Syntax and Return Value:

The syntax of the fork() system function is as follows:

pid_t fork(void);

The fork() system function does not accept any argument. It returns an integer of the type pid_t.

On success, fork() returns the PID of the child process which is greater than 0. Inside the child process, the return value is 0. If fork() fails, then it returns -1.

Simple fork() Example:

A simple fork() example is given below:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
int main(void) {
  pid_t pid = fork();
 
  if(pid == 0) {
    printf("Child => PPID: %d PID: %dn", getppid(), getpid());
    exit(EXIT_SUCCESS);
  }
  else if(pid > 0) {
    printf("Parent => PID: %dn", getpid());
    printf("Waiting for child process to finish.n");
    wait(NULL);
    printf("Child process finished.n");
  }
  else {
    printf("Unable to create child process.n");
  }
 
  return EXIT_SUCCESS;
}

Here, I used fork() to create a child process from the main/parent process. Then, I printed the PID (Process ID) and PPID (Parent Process ID) from child and parent process. On the parent process wait(NULL) is used to wait for the child process to finish. On the child process, exit() is used to finish the child process. As you can see, the PID of the parent process is the PPID of the child process. So, the child process 24738 belongs to the parent process 24731.

You can also use functions to make your program more modular. Here, I used processTask() and parentTask() functions for the child and parent processes respectively. This is how fork() is actually used.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
void childTask() {
  printf("Hello Worldn");
}
 
void parentTask() {
  printf("Main task.n");
}
 
int main(void) {
  pid_t pid = fork();
 
  if(pid == 0) {
    childTask();
    exit(EXIT_SUCCESS);
  }
  else if(pid > 0) {
    wait(NULL);
    parentTask();
  }
  else {
    printf("Unable to create child process.");
  }
 
  return EXIT_SUCCESS;
}

The output of the above program:

Running Multiple Child Processes using fork() and Loop:

You can also use loop to create as many child processes as you need. In the example below, I have created 5 child processes using for loop. I also printed the PID and PPID from the child processes.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
int main(void) {
  for(int i = 1; i <= 5; i++) {
    pid_t pid = fork();
 
    if(pid == 0) {
      printf("Child process => PPID=%d, PID=%dn", getppid(), getpid());
      exit(0);
    }
    else  {
      printf("Parent process => PID=%dn", getpid());
      printf("Waiting for child processes to finish…n");
      wait(NULL);
      printf("child process finished.n");
    }
  }
 
  return EXIT_SUCCESS;
}

As you can see, the Parent process ID is the same in all the child processes. So, all of them belong to the same parent. They also execute in linear fashion. One after the other. Controlling child processes is a sophisticated task. If you learn more about Linux system programming and how it works, you will be able to control the flow of these processes anyway you like.

Real Life Example:

Different complex mathematical computations such as md5, sha256 etc hash generation requires a lot of processing power. Instead of computing things like that in the same process as the main program, you can just calculate the hash on a child process and return the hash to the main process.

In the following example, I’ve generated a 4-digit PIN code in a child process and send it to the parent process, the main program. Then, I printed the PIN code from there.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
int getPIN() {
  // use PPID and PID as the seed
  srand(getpid() + getppid());
  int secret = 1000 + rand() % 9000;
  return secret;
}
 
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…n");
    wait(NULL);
    printf("Bytes read: %ldn", readBytes);
    printf("PIN: %dn", 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;
}

As you can see, each time I run the program, I get a different 4-digit PIN code.

So, that’s basically how you use fork() system call in Linux. Thanks for reading this article.

Sandclock IDC thành lập vào năm 2012, là công ty chuyên nghiệp tại Việt Nam trong lĩnh vực cung cấp dịch vụ Hosting, VPS, máy chủ vật lý, dịch vụ Firewall Anti DDoS, SSL… Với 10 năm xây dựng và phát triển, ứng dụng nhiều công nghệ hiện đại, Sandclock IDC đã giúp hàng ngàn khách hàng tin tưởng lựa chọn, mang lại sự ổn định tuyệt đối cho website của khách hàng để thúc đẩy việc kinh doanh đạt được hiệu quả và thành công.
Bài viết liên quan

Sending an Email in Python

Sending an Email is one of the most common tasks I need to do in the web applications and other projects I create. With...
28/12/2020

Openstack Kolla [Phần 3] Hướng dẫn tạo máy ảo trên cụm Openstack

Tiếp tục với series hướng dẫn vài đặt OpenStack bằng Kolla Ansible. Ở bài viết những bài viết...
30/12/2020

Hướng dẫn cài đặt MariaDB Server phiên bản 10.4.7 trên CentOS 7

MariaDB là một nhánh của MySQL( một trong những CSDL phổ biến trên thế giới ), là máy...
30/12/2020
Bài Viết

Bài Viết Mới Cập Nhật

Hướng dẫn chuyển đổi windows server windows evaluation to standard và active windows server 2008 + 2012 + 2016 + 2019
26/10/2021

How to Update Ubuntu Linux
24/10/2021

Squid Proxy Manager cài đặt và quản lý Proxy Squid tự động trên ubuntu
20/10/2021

Hướng dẫn cài đặt Apache CloudStack 4.15.2.0
19/10/2021

Hướng dẫn ký file PDF bằng chữ ký số (chữ ký điện tử) và sửa lỗi mới nhất 2021 foxit reader
19/10/2021