daemon

Concept:

Daemons, also known as daemons, are background service processes in Linux. Periodically perform certain tasks or wait for certain events to occur.

Linux systems have many daemons, and most services are implemented using daemons. For example: our TFTP, Samba, NFS and other related services.

UNIX daemons are typically named *d, such as HTTPD, telnetd, and so on.

Life cycle:

Daemons run for a long time, often starting when the system starts and not stopping until the system is shut down.

Daemons are not terminal dependent

All processes that start at a terminal are attached to this terminal, which is called the control terminal of these processes. When the control terminal is closed, the corresponding process will be automatically shut down. We usually write process, an infinite loop program, we do not know when CTRL + C, how to close it ah, is not to close the terminal ah. That is to say, when we close the terminal, we also close our program, but for daemons, their life cycle daemons need to break through this limitation. They run from the start until the whole system is shut down, so the daemons cannot rely on the terminal.

Viewing daemons

Ps axj a: Displays all processes that have no control terminal. J: Displays job-related information (columns to be displayed) : Session period ID (SID), Process group ID (PGID), Control terminal (TT), Terminal Process group ID (TRGID)

• All daemons are started as superuser (UID 0); • No control terminal (TTY?) ; • The terminal process group ID is -1(TPGID indicates the terminal process group ID. The value indicates the foreground process group related to the control terminal. If the value is not related to any terminal, the value is -1. • Parent of all daemons:

Historically, Linux has been started with the init process; The following command is used to start the service. This approach has two disadvantages:1.Long startup time. The init process is a serial startup process. The next process is started only after the previous process is started.2.The startup script is complex. The init process simply executes the startup script, no matter what else. Scripts have to handle situations on their own, which often makes them very long.Copy the code

Systemd was created to solve these problems. Its design goal is to provide a complete solution for system startup and management. By Linux convention, the letter D is short for daemon. The meaning of the name Systemd is that it guards the entire system.

Process group, session, control terminal

• process group

Each process in the shell belongs to a process group. The purpose of creating a process group is to simplify the operation of sending a signal to all processes in the group. That is, if a signal is sent to a process group, all processes in the group will receive the signal [easy management].

• PGID Indicates the process group ID

All processes in a process group have the same PGID, which is equal to the PID of the group leader. Process group leader: A process in a process group acts as the group leader. Process group ID (PGID) Is equal to the PROCESS ID of the process group length. Given a process, you can call getPgrp to get the ID of the process group to which the process belongs. A process can join an existing process group or create a new process group by using another system call setpgrp.

If the kernel supports _POSIX_JOB_CONTROL (this macro is defined), the kernel creates a process group for each command line on the Shell (which can be multiple commands connected via pipes, etc.). At this point, a process group is not a process concept, but a shell, so there is no variable like a process group ID stored in a task_struct.

The life cycle of a process group is until the last process in the group terminates or it leaves the process group by joining another process group.

The session

Generally, a user logs in and creates a session. Each session is also identified by an ID (SID). The first process you log in to is called the Session leader, which is usually a shell/bash. For the session lead process, its PID=SID.

Control terminal

A session typically has a control terminal to perform IO operations. When a terminal is opened by the lead process of the session, it becomes the controlling terminal of the session. The session lead process that connects to the control terminal is also called the controlling process. A session can have only one control terminal.

Foreground process group

This process group is a process group that can read and write data to the terminal device. For example, you can log in to shell (e.g. bash) by calling int tcsetpgrp(int fd, pid_t PGRP); Function is set to a process group PGRP to associate with the terminal device fd. After this function is executed successfully, the process group PGRP becomes a foreground process group.

Background process group

Processes in this process group can only write to terminal devices.

ID of a terminal process group

Each process also has an attribute, the Terminal Process group ID(TPGID), that identifies whether a process is in a process group associated with the terminal. TPGID=PGID in the foreground process group, and PGID≠TPGID in the background process group. If the process is independent of any terminal, the value is -1. Compare them to determine whether a process belongs to a foreground or background process group.

Process groups, conversational periods, and control terminal relationships

  1. Each session has only one foreground process group, but there can be zero or more background process groups.
  2. Inputs and signals generated on the control terminal are sent to all processes in the foreground process group of the session. For Output, it is shared between foreground and background, that is, the printout of foreground and background will be displayed on the screen.
  3. When the connection on the terminal is disconnected (for example, the network is disconnected or the Modem is disconnected), a hang signal is sent to the controlling process.
  4. A user logs in and creates a session. Only one foreground process group exists in a session, but multiple background process groups can exist. The first process created after the first login is the shell, which is the lead process of the session. This lead process is in a foreground process group by default and opens a control terminal to read and write data. When you run a command (without &) in the shell to create a new process group, if there are multiple commands in the command line, multiple processes will be created, and these processes are in the new process group. The shell sets the new process group as the foreground process group and temporarily sets itself as the background process group.

For example,

  1. Open the first terminal to execute the command:
ping 127.0. 01. -aq | grep icmp &  Ping -q does not display timeout information, set it to the background and run it
Copy the code
  1. Continue executing the command at the first terminal and create a new process group in the foreground. 【 Notice no &】
ping 127.0. 01. -aq | grep icmp // Create a new process group in the foreground,
Copy the code
  1. Start the second terminal and run it
 ps axj | grep pts/0That is to filter only PTS /0PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND2109  2111  2111  2111 pts/0     2538 Ss    1000   0:01 bash
 2111  2503  2503  2111 pts/0     2538 S     1000   0:00 ping 127.0. 01. -aq
 2111  2504  2503  2111 pts/0     2538 S     1000   0:00 grep --color=auto icmp
 2111  2538  2538  2111 pts/0     2538 S+    1000   0:00 ping 127.0. 02. -aq
 2111  2539  2538  2111 pts/0     2538 S+    1000   0:00 grep --color=auto timeo
Copy the code

• There are three process groups, PGID 2111, 2503, and 2538. We can see that the connected with | ping and grep is in a process group. • process group 2538 is a foreground process group because its PGID==TGPID and process group 2503 is a background process group

  1. Execute Ctrl+C on the first terminal
  2. In the second terminal to ps axj | grep PTS / 0
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 2109  2111  2111  2111 pts/0     2111 Ss+   1000   0:01 bash
 2111  2503  2503  2111 pts/0     2111 S     1000   0:00 ping 127.0. 01. -aq
 2111  2504  2503  2111 pts/0     2111 S     1000   0:00 grep --color=auto icmp
Copy the code

All processes in the foreground process group (2538) have disappeared, indicating that a signal is sent to all processes in the foreground process group (2111).

Daemon process creation process

The process for creating a daemon process is as follows:

1.The child process is created, and the parent process exits2.Create a new session in a child process3.Change the current directory to root4.Reset the file permission mask5.Close the file descriptorCopy the code

1. Create a child process. The parent process exits

Since the daemon is detached from the control terminal, completing the first step creates the illusion in the shell terminal that a program has finished running. After that, all the follow-up work is completed in the child process, and the user can execute other commands in the shell terminal, so as to formally achieve the separation from the control terminal.

Because the parent process exits before the child process, the child process has no parent process and becomes an orphan process. In Linux, whenever the system finds an orphan process, it is automatically adopted by process 1. The original child becomes a child of the init process.

2. Create a new session in the child process

The setsid() function. After a process calls setsid(), the following events occur:

• The kernel first creates a new session and makes this process the leader of the session. • With the creation of the session, a new process group is created and this process becomes the group leader. • The process is not associated with any control terminal at this time. Call tcsetPGRp separately if necessary, as described in the foreground process group section.Copy the code

Calling setsid() does three things:

• Take the process out of the original session. • Free the process from the control of the original process group. • Take the process out of the control of the original controlling terminal.Copy the code

So why is setsid() called when the daemon is created?

The reader will recall the first step in creating a daemon, where fork() was called to create the child process and then to exit the parent process. When fork() is called, the child process completely copies the parent process’s session period, process group and control terminal, etc., although the parent process exits, but the original session period, process group and control terminal, etc., is not truly independent. The setsid() function makes the process completely independent from all other processes and terminals.

See man 2 setSID for details.

3. Change the current directory to the root directory

This is a necessary step. A child process created using fork() inherits the parent process’s current working directory.

In the process of running, the current directory of the file system (such as “/ MNT/USB”, etc.) can not be uninstalled, which will cause a lot of trouble for future use (such as the system for some reason to enter the single user mode).

Therefore, it is common practice to have “/” as the current working directory of the daemon to avoid the above problems. Of course, if necessary, you can also change the current working directory to another path, such as/TMP. A common function to change the working directory is chdir().

4. Reset the file permission mask

The file permission mask masks the corresponding bits in the file permission.

For example, a file permission mask of 050 would mask the readable and executable permissions of the filegroup owner. Since the newly created child process using fork() inherits the file permission mask of the parent process, the child process has a lot of trouble using the file.

Therefore, setting the file permission mask to 0 greatly increases the flexibility of the daemon. The function that sets the file permission mask is umask(). In this case, the usual use is umask(0). That is to give maximum capacity.

5. Close the file descriptor

As with file permission masks, children created using fork() inherit open files from their parent. These open files may never be read or written by the daemon, but they still consume system resources and may cause the file system to be unmounted.

After step (2) above, the daemon has lost contact with the controlling terminal, so it is not possible for characters entered from the terminal to reach the daemon, and it is not possible for characters printed by the daemon using normal methods (such as printf()) to be displayed on the terminal.

Therefore, the three files with file descriptors 0, 1, and 2 (commonly referred to as input, output, and error) have lost their value and should also be closed.

Code implementation

/* Pay attention to a mouthful of Linux */
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h> 
#include <fcntl.h>
#include <string.h>

int main(a)
{
	pid_t pid;
	int i, fd;
	char *buf = "This is a Daemon\n";

	pid = fork();
	if (pid < 0) {
		printf("Error fork\n");
		exit(1);
	} 
	
	/* First step, the parent exits */
	if (pid > 0) {
		exit(0);	
	}
	/* Step 2 */
	setsid();
	/* Step 3 */		
	chdir("/");		
	/* Step 4 */
	umask(0);
	/* Step 5 */		
	for(i = 0; i < getdtablesize(); i++) 
	{
		close(i);
	}
	
	/* At this point, the daemon process is created. Since the daemon is completely out of the control terminal at this point, it cannot output error messages to the control terminal through printf or perror like other normal processes. A common way to do this is to use the syslog service to input error messages from the program into the system log file. * This program focuses on demonstrating the steps of creating a daemon process, not demonstrating syslog. * /
	while(1) {
		if ((fd = open("/tmp/daemon.log", 
				O_CREAT|O_WRONLY|O_APPEND, 0600))"0) {
			exit(1);
		}
		write(fd, buf, strlen(buf) + 1);
		close(fd);
		sleep(10);
	}
	
	exit(0);
}
Copy the code

The execution result

As can be seen from the above figure:

• The UID of the./run daemon process is 0.

• No control terminal (TTY?) ;

• The terminal process group ID is -1.

• The parent daemon process is 1516, or Systemd.

More Linux dry goods, please pay attention to: a mouthful of Linux