Other Processes


Advertisements

So far, we have discussed about processes, its creation, parent and child processes, etc. The discussion will be incomplete without discussing other related processes, such as the Orphan process, Zombie process and Daemon process.

Orphan Process

As indicated by the name, orphan implies parentless process. When we run a program or application, the parent process for the application is shell. When we create a process using fork(), the newly created process is the child process and the process that created the child is the parent process. In turn, the parent process of this is shell. Of course, the parent of all the processes is init process (Process ID → 1).

The above is a usual scenario, however, what happens if the parent process exits before the child process. The result is, the child process now becomes the orphan process. Then what about its parent, its new parent is the parent of all the processes, which is nothing but init process (Process ID – 1).

Let us try and understand this using the following example.

/* File Name: orphan_process.c */

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

int main() {
   int pid;
   system("ps -f");
   pid = fork();
   if (pid == 0) {
      printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
      sleep(5);
      printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
      system("ps -f");
   } else {
      printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
      sleep(2);
      exit(0);
   }
   return 0;
}

Compilation and Execution Steps

UID         PID   PPID  C STIME TTY    TIME CMD
4581875  180558      0  0 09:19  ?     00:00:00 sh -c cd /home/cg/root/4581875; 
                                       timeout 10s main
4581875  180564 180558  0 09:19  ?     00:00:00 timeout 10s main
4581875  180565 180564  0 09:19  ?     00:00:00 main
4581875  180566 180565  0 09:19  ?     00:00:00 ps -f
Parent: pid is 180565 and ppid is 180564
UID         PID   PPID  C STIME TTY    TIME CMD
4581875  180567      0  0 09:19  ?     00:00:00 main
4581875  180820 180567  0 09:19  ?     00:00:00 ps -f
Child: pid is 180567 and ppid is 180565
Child: pid is 180567 and ppid is 0

Zombie Process

In simple terms, assume that you have two processes, namely the parent and the child process. It is the responsibility of the parent process to wait for child process and then clean up the child process entry from the process table. What if the parent process is not ready to wait for the child process, and in the meantime the child process gets its job done and exits? Now, the child process would become the zombie process. Of course, the zombie process is cleaned up after the parent process becomes ready.

Let us understand this with the help of an example.

/* File Name: zombie_process.c */

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

int main() {
   int pid;
   pid = fork();
   if (pid == 0) {
      system("ps -f");
      printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
      exit(0);
   } else {
      printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
      sleep(10);
      system("ps aux|grep Z");
   }
   return 0;
}

Compilation and Execution Steps

UID         PID   PPID  C STIME TTY    TIME CMD
4581875  184946      0  0 09:20  ?     00:00:00 sh -c cd /home/cg/root/4581875; 
                                       timeout 10s main
4581875  184952 184946  0 09:20  ?     00:00:00 timeout 10s main
4581875  184953 184952  0 09:20  ?     00:00:00 main
4581875  184954 184953  0 09:20  ?     00:00:00 main
4581875  184955 184954  0 09:20  ?     00:00:00 ps -f
Child: pid is 184954 and ppid is 184953

Daemon Process

In simple terms, the process which doesn’t have any associated shell or terminal is known as the daemon process. Why this is needed? These are the processes which run in the background to perform actions at predefined intervals and also respond to certain events. The daemon process should not have any user interaction, since it runs as a background process.

The internal Linux daemon processes usually ends with the letter “d” such as Kernel Daemons (ksoftirqd, kblockd, kswapd, etc.), Printing Daemons (cupsd, lpd, etc.), File Service Daemons (smbd, nmbd, etc.), Administrative database daemons (ypbind, ypserv, etc.), Electronic Mail Daemons (sendmail, popd, smtpd, etc.), Remote Login and Command Execution Daemons (sshd, in.telnetd, etc.), Booting and Configuration Daemons (dhcpd, udevd, etc.), init process (init), cron daemon, atd daemon, etc.

Now let us see how to create a daemon process. Following are the steps −

Step 1 − Create a child process. Now we have two processes – the parent process and the child process

Usually the process hierarchy is SHELL → PARENT PROCESS → CHILD PROCESS

Step 2 − Terminate the parent process by exiting. The child process now becomes the orphan process and is taken over by init process.

Now, the hierarchy is INIT PROCESS → CHILD PROCESS

Step 3 − Calling the setsid() system call creates a new session, if the calling process is not a process group leader. Now the calling process becomes the group leader of the new session. This process will be the only process in this new process group and in this new session.

Step 4 − Set the process group ID and session ID to PID of the calling process.

Step 5 − Close the default file descriptors (standard input, standard output, and standard error) of the process as the terminal and shell are now disconnected from the application.

/* Filename: daemon_test.c */

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, char *argv[]) {
   pid_t pid;
   int counter;
   int fd;
   int max_iterations;
   char buffer[100];
   if (argc < 2)
   max_iterations = 5;
   else {
      max_iterations = atoi(argv[1]);
      if ( (max_iterations <= 0) || (max_iterations > 20) )
      max_iterations = 10;
   }
   pid = fork();
   
   // Unable to create child process
   if (pid < 0) {
      perror("fork error\n");
      exit(1);
   }
   
   // Child process
   if (pid == 0) {
      fd = open("/tmp/DAEMON.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
      if (fd == -1) {
         perror("daemon txt file open error\n");
         return 1;
      }
      printf("Child: pid is %d and ppid is %d\n", getpid(), getppid());
      printf("\nChild process before becoming session leader\n");
      sprintf(buffer, "ps -ef|grep %s", argv[0]);
      system(buffer);
      setsid();
      printf("\nChild process after becoming session leader\n");
      sprintf(buffer, "ps -ef|grep %s", argv[0]);
      system(buffer);
      close(STDIN_FILENO);
      close(STDOUT_FILENO);
      close(STDERR_FILENO);
   } else {
      printf("Parent: pid is %d and ppid is %d\n", getpid(), getppid());
      printf("Parent: Exiting\n");
      exit(0);
   }
   
   // Executing max_iteration times
   for (counter = 0; counter < max_iterations; counter++) {
      sprintf(buffer, "Daemon process: pid is %d and ppid is %d\n", getpid(), getppid());
      write(fd, buffer, strlen(buffer));
      sleep(2);
   }
   strcpy(buffer, "Done\n");
   write(fd, buffer, strlen(buffer));
   
   // Can't print this as file descriptors are already closed
   printf("DoneDone\n");
   close(fd);
   return 0;
}

Parent: pid is 193524 and ppid is 193523
Parent: Exiting
4581875  193525      0  0 09:23  ?      00:00:00 main
4581875  193526 193525  0 09:23  ?      00:00:00 sh -c ps -ef|grep main
4581875  193528 193526  0 09:23  ?      00:00:00 grep main
4581875  193525      0  0 09:23  ?      00:00:00 main
4581875  193529 193525  0 09:23  ?      00:00:00 sh -c ps -ef|grep main
4581875  193531 193529  0 09:23  ?      00:00:00 grep main
Advertisements