What is a daemon?

Before understanding the daemon, you need to know what is a terminal? What is homework? What is a process group? What is conversation?

In Linux, the interface between each system and the user is called the terminal. Every process running from the terminal will be attached to the terminal. This terminal is called the control terminal of these processes. When the control terminal is closed, the corresponding process will be closed automatically.

A daemon is a process that has a long life cycle, is independent of the control terminal and performs certain tasks periodically. The reason to leave the terminal is to prevent the process from being interrupted by any terminal information.

Therefore, to create a daemon, we need to separate the process from the terminal.

The shell is divided into front and background jobs to control not processes but jobs. A job consists of multiple processes. Shell can run one foreground job and any number of background jobs, which is called job control. bash is an independent job.

A process group is a collection of one or more processes. Each process has a PID and a PGID. PGID is the PID of the team leader. Process groups are usually associated with a job and can receive signals from the same terminal.

Of course, process group and job are not two completely equivalent concepts: if a process in the job creates a new sub process, the sub process does not belong to the job, but belongs to the process group.

A Session is a collection of one or more process groups. A Session can have a control terminal. In a Session, there is a foreground job and several background jobs. The Session SID is the PID of the Session process.

Why can only one foreground job run? When we start a new job in the foreground, the shell is mentioned to the background, so the shell can no longer accept our instructions and run analytically. However, if the foreground process exits, the shell will be brought to the foreground and can continue to accept our commands and run analytically.

So, how to cut off the relationship between process and terminal?

First, call setsid () to make the child process the new session leader. After the setsid() call is successful, the process becomes the new session leader and the new process leader, and is separated from the original login session and process group.

A prerequisite for calling setsid () is that the process cannot be a leader process, so you need to fork and kill the parent process first, and the caller of setsid () is the child process.

Next, to prevent the process from reopening the control terminal. The process that can open the control terminal must be the process group leader, so we need to fork () again and kill the parent process, and the remaining child process will no longer be the first process and the process group leader. Therefore, the child process no longer has the permission to open the terminal. So far, we have completely cut off the connection between the process and the terminal.

Finally, close the open file descriptor or redirect the open file descriptor. Because the process will inherit the file descriptor from the parent process, if it is not closed, it will waste system resources.

If you want to change the directory where the process is located, you can call chdir("/") to move the daemon to the root directory.

If the daemon has child processes, the daemon needs to wait for the child process to exit, otherwise the child process will become a zombie process. In order to reduce the burden of the daemon and prevent its recycling child processes from affecting the server concurrency performance, signal (sigcld, sig_ign) can be used to ignore sigcld. This can prevent the zombie process.

#include <unistd.h>   
#include <signal.h>   
#include <fcntl.h>  
#include <sys/syslog.h>  
#include <sys/param.h>   
#include <sys/types.h>   
#include <sys/stat.h>   
#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
  
int init_daemon(void)  
{   
    int pid;   
    int i;  
      
    // 1) Shield some signals that control the operation of the terminal  
    signal(SIGTTOU,SIG_IGN);   
    signal(SIGTTIN,SIG_IGN);   
    signal(SIGTSTP,SIG_IGN);   
    signal(SIGHUP ,SIG_IGN);  
   
    // 2) Run in the background  
    if( pid=fork() ){ // Parent process  
        exit(0); //The parent process ends and the child process continues  
    }else if(pid< 0){ // error  
        perror("fork");  
        exit(EXIT_FAILURE);  
    }  
      
    // 3) Out of control terminal, login session and process group  
    setsid();    
      
    // 4) Prohibit the process from reopening the control terminal, which is a defensive programming and an optional step
    if( pid=fork() ){ // Parent process  
        exit(0);      // End the first subprocess and the second subprocess continues (the second subprocess is no longer the session leader)
     
    }else if(pid< 0){ // error  
        perror("fork");  
        exit(EXIT_FAILURE);  
    }    
      
    // 5) Close open file descriptor  
    // NOFILE is < sys / param h> Macro definition for  
    // NOFILE is the maximum number of file descriptors. Different systems have different restrictions  
    for(i=0; i< NOFILE; ++i){  
        close(i);  
    }  
      
    // 6) Change current working directory  
    chdir("/tmp");   
      
    // 7) Resets the file creation mask because the process inherits the file creation mask from the parent process that created it. It may modify the access rights of files created by the daemon.
    umask(0);    
      
    // 8) Processing SIGCHLD signal  
    signal(SIGCHLD,SIG_IGN);  
      
    return 0;   
}   
  
int main(int argc, char *argv[])   
{  
    init_daemon();  
      
    while(1);  
  
    return 0;  
} 

Added by JP128 on Mon, 03 Jan 2022 21:40:44 +0200