In-depth understanding of daemons from the concepts of process groups, sessions, and terminals

In-depth understanding of daemons from the concepts of process groups, sessions, and terminals

1. Write in front

"Daemon" is a long-running background service process of Linux, and some people call it "elf process". Our common services such as httpd, named, and sshd all run in Daemon mode. Usually, the service name ends with the letter d, which is the first letter of Daemon. Compared with ordinary processes, it has the following characteristics:

  • No control terminal required (no user interaction required)
  • run in the background
  • The life cycle is relatively long, generally with the system startup and shutdown

Second, the necessity of the daemon process

Why should it be set as a daemon process, can't it be a normal process?

When we enter a similar ./helloworldprogram at the command line prompt, the terminal is occupied while the program is running, and no other operations can be performed at this time. Even if the usage ./helloworld &mode runs in the background, when there is a problem with the network connecting the terminal, the running program will be interrupted. These factors are not friendly to long-running services, and "daemons" can solve this problem very well.

3. Understanding of Process Groups, Sessions, and Terminals

The "daemon" is not complicated to understand, and there are basically fixed routines in code writing. If you want to deeply understand the basic principle of "daemon", you must first understand the concepts of Linux process, process group, session, terminal and so on.

1. Process

  • A process is the smallest unit of resource allocation in Linux
  • Foreground process, for example:$ ./hello
  • Background processes, such as this: $ ./hello &release the occupancy of the controlling terminal

2. Process group

Each process belongs to a process group, and a process group can contain one or more processes. There is a process group leader in the process group, and the process ID of the group leader is the process group ID (PGID)

$ ps -o pid,pgid,ppid,comm | cat
  PID  PGID  PPID  COMMAND
10179  10179 10177 bash
10263  10263 10179 ps
10264  10263 10179 cat

The following is a simple example to understand the process group

  • bash: The process and process group IDs are both 10179, and the parent process is actually sshd (10177)
  • ps: The process and process group IDs are both 10263, and the parent process is bash (10179), because it is a command executed on the shell
  • cat: The process group ID is the same as that of ps, and the parent process is also bash (10179)

It is easy to understand that Bash is the shell process, and the parent process of the shell is sshd; ps and cat run together through the pipe symbol, and belong to a process group whose parent processes are all Bash; a process group is also called "job".

3. Session

Multiple process groups form a "session", the process that establishes the session is the leader process of the session, and the process ID is the SID of the session. Each process group in a session is called a "job". Sessions can have one process group called "foreground jobs" for the session, and other process groups called "background jobs"

A session can have a controlling terminal, and when the controlling terminal has input and output both are passed to the foreground process group, eg Ctrl + Z. The significance of a session is that multiple jobs can be controlled by one terminal, one is operated in the foreground, and the other is run in the background.

4. Operations related to front-end and back-end operations

Let the job run in the background by:

$ ping localhost >/dev/null &
[1] 10269    # 终端显示
# [1]:作业ID  10269:进程组ID

Signal SIGTERM to background jobs

$ kill -SIGTERM -10269  # 发信号给进程组
$ kill -SIGTERM %1      # 发信号给作业1

Let the background process switch to the foreground:

$ fg %1
# ping 进程重新切到前台

Fourth, write the daemon

Writing a daemon may seem complicated, but it actually follows a specific process.

1. Create a child process, and the parent process exits

After a process fork, the parent process exits. There are 2 reasons for this:

  • If the daemon process is started through the shell and the parent process exits, the shell will consider that the task is completed, and the child process is adopted by init
  • The child process inherits the process group ID of the parent process, which ensures that the child process is not the process group leader, because the subsequent calls setsid()must not be the process group leader .

2. The child process creates a new session

Call to setsid()create a new session and become the new session leader. This step is mainly to break away from the session, process group, and terminal that inherit the parent process.

3. Prevent child processes from reopening the terminal

At this moment, the child process is the session leader. In order to prevent the child process from reopening the terminal, it exits the parent process after fork again, which is the child process. At this time, child process 2 is no longer the session leader and can no longer open the terminal. In fact, this step is not necessary, but adding this step will make it more rigorous.

4. Set the current directory as the root directory

If the current working directory of the daemon is a /usr/homedirectory, the administrator /usrwill report an error when unmounting the partition. To avoid this problem, a chdir()function can be called to set the working directory to the root directory /.

5. Set the file permission mask

File permission mask means to mask out the corresponding bit in the file permission. Since the child process created using the fork()function inherits the file permission mask of the parent process, this brings a lot of trouble to the child process using the file. Therefore, setting the file permission mask to 0 can greatly enhance the flexibility of the daemon. The usual way to use it is umask(0).

6. Close the file descriptor

Child processes will inherit open files, which occupy system resources and may cause the file system where they are located to be unmountable. At this point, the daemon is disconnected from the terminal, and the input, output, and error descriptors that are often said should also be closed.

Fifth, the error handling of the daemon process

Since the daemon is detached from the terminal, it cannot output error messages to the controlling terminal, and even gdb cannot debug it properly. A common method is to use the syslog service to enter error messages into /var/log/messages.

syslog is a system log management service in Linux, maintained by the daemon syslogd. The daemon reads a configuration file when it starts /etc/syslog.conf. This file determines where different kinds of messages are sent.

Six, daemon coding example

pid_t pid, sid;
int i;
openlog("daemon_syslog", LOG_PID, LOG_DAEMON);
pid = fork(); // 第1步
if (pid < 0) exit(-1);
else if (pid > 0) exit(0);  // 父进程第一次退出
if ((sid = setsid()) < 0)   // 第2步
{
    syslog(LOG_ERR, "%s\n", "setsid");
    exit(-1);
}
// 第3步 第二次父进程退出
if ((pid = fork()) > 0) exit(0);
if ((sid = chdir("/")) < 0) // 第4步
{
    syslog(LOG_ERR, "%s\n", "chdir");
    exit(-1);
}
umask(0); // 第5步
// 第6步:关闭继承的文件描述符
for(i = 0; i < getdtablesize(); i++)
{
    close(i);
}
while(1)
{
    do_something();
}
closelog();
exit(0);

Basically, all the content of the daemon process has been explained clearly here. There is a lot of content, and the concept is relatively obscure. If you want to understand more thoroughly, you may need to read it several times.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325128489&siteId=291194637