The relationship between Linux terminal and process (1) -[Linux Communication Architecture Series]

Table of Contents of Series Articles

C++ skills series
Linux communication architecture series
C++ high-performance optimization programming series
in-depth understanding of software architecture design series
advanced C++ concurrent thread programming

Looking forward to your attention! ! !
Insert image description here

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

1. Linux process relationship

1.1 Linux process related concepts "process relationship, process group, process session"

There is a structural relationship between processes, as shown in the figure:

Insert image description here

Figure 1.1 Process relationship diagram

The top init process is the "ancestor" process (created by the kernel itself when the operating system starts, with superuser privileges). The process ID (PID) of the init process is 1, and other processes in the system should be forked (created) by it or its child processes.

Enter the ps -ef command in the terminal to view the results:
Insert image description here

Figure 1.2 The process with PID 1 is the init process

Further analysis of process relationships:

A process has a process ID (PID) and a parent process ID (PPID). Another thing to know: each process can also belong to a process group (divided into groups for easier management, for example, you can send a message to the entire group, etc.). “进程组”代表一个或多个进程的集合. Each process group has a unique process group ID, and each process in a process group can independently receive various signals from the terminal. You can create a process group, join a process group, etc. by calling system functions.

After understanding the concept of process groups, we introduce a new concept: “会话”(Sessiond)是一个或多个进程组的集合。

Insert image description here

Figure 1.3 A session contains one or more process groups, and a process group contains one or more processes.

Generally speaking, if special system functions are not called for special processing, all programs running on a bash (shell) will belong to a session, and this session has a session leader, which is the session leader that creates the session. session process), this shell (bash) is usually the session leader. In addition, you can also call functions to create new sessions.

2. The relationship between terminal and process

2.1 Terminal and bash process

Start the Ubuntu Linux virtual machine, use Xshell to connect to the virtual machine, and enter the following command:
ps -ef | grep bash

The process ID of 19501 is the bash process (the process generated by Xshell linking to the Ubuntu Linux virtual machine), as shown in Figure 2.1:
Insert image description here

Figure 2.1.1 Find processes containing the word bash (1)

Create another Xshell link virtual machine session window and enter the ** ps -ef | grep bash** command, as shown in Figure 2.12:
Insert image description here

Figure 2.1.2 Find processes containing the word bash (2)

It can be seen that there are 2 bash processes at this time (because there are two Xshells connected to the Ubuntu Linux virtual machine), and the process IDs are 19501 and 3253 respectively. We can see pts/0 and pts/1 in the picture, and pts is 虚拟终端.

Each virtual machine terminal connected to the Ubuntu Linux virtual machine will open a bash process (also called shell - shell). The black window into which various commands are entered is bash, which is used to interpret the commands entered by the user. After entering a command in Xshell and pressing the Enter key, the command will be interpreted and executed by the bash process ( bash就是shellthat is, it 命令行解释器is an executable program).

You can use the whereis command to find the location of the bash executable program, as shown in Figure 2.13:
whereis bash
Insert image description here

Figure 2.1.3 Use the whereis command to find the location of the bash executable program

2.2 Starting the process on the terminal

Write the nginx.c code yourself in VSCode, the content is as follows:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *const *argv)
{
    
    
        printf("hello nginx\n");
        for(;;)
        {
    
    
                sleep(1);
                printf("休息1s\n");
        }
        printf("程序退出!再见!\n");
}

Run ./nginx, and enter in another terminal window:
ps -la
-l代表比较长的输出显示格式;-a代表显示终端上的所有进程(包括其他终端的进程)

Insert image description here

Figure 2.2.1 Result of executing ps -la
This is an infinite loop program that will repeatedly output "rest for 1 second" and can be stopped by pressing the `Ctrl + C` key combination.

2.3 Why does the process exit as soon as the terminal is logged out?

Now, start the nginx executable program you wrote in a terminal again, and then open two Xshell terminals to keep the three terminals running.

Enter the following command in the terminal:
ps -eo pid,ppid,sid,tty,pgrp,comm | grep -E 'bash|PID|nginx'

e代表所有进程;o代表自己指定显示哪些列(sid表示session id, tty表示终端, pgrp表示进程组, comm表示执行的命令);grep命令中,-E代表要开启扩展正则表达式功能,用于配合后面的bash|PID|nginx以显示特定名字的进程;| 代表或者关系;bash|PID|nginx代表bash、PID、nginx这几个字符串中的某个出现就会被显示。
Insert image description here

Figure 2.3.1 Use the ps command to display the process with the specified name

Observe Figure 2.3.1:

(1) The PPID of the nginx process is 3253, and 3253 is the PID of a certain bash, indicating that nginx is a child process of a certain bash.

(2) The SID of the nginx process is 3253, and 3253 is the PID of this bash, and it is also the SID of this bash. That is to say, the SID of this bash is equal to the PID, which means that this bash is the session header of the entire session. Process (session leader).

The PID and PGRP of the nginx process are both 14942, indicating that nginx is a group of its own.

(3) The bash process and nginx process with PID=3253, their TT (tty) are both pts/0 (terminal numbered 0).

(4) After the bash process receives the SIGHUP signal, it will send the signal to all processes in the session. The default action of the process that receives the SIGHUP signal is to exit.

After analyzing it here, you should understand why the process exits as soon as the terminal is logged out.

2.4 Use of strace tool

strace is a debugging analysis and diagnostic tool in Linux. It is powerful and can be used to track the system calls of the process and the signals received when the program is executed. Now let’s see how to use the strace tool.

(1) Execute the following command:sudo strace -e trace=signal -p 23099

This command is used to track system calls related to signals on the process with PID 23099 (nginx process). In other words, this command attaches the trace tool to process 23099. as the picture shows:
Insert image description here

Figure 2.4.1 Attach the strace tool to the process 23099 (nginx) process

(2) Now open the third terminal window and use strace to attach the parent process of the nginx process with PPID 3253 (bash)
sudo strace -e trace=signal -p 3253
Insert image description here

Figure 2.4.2 Attach the strace tool to the 3253 process (bash)

(3) Now close the process window running nginx and you will find that the other two windows running strace have content output.

First, look at the output of the terminal window attached to the nginx process:
Insert image description here

Figure 2.4.3 The strace tool attached to the nginx process has output

As can be seen from Figure 2.4.3, the signal is SIGHUP, sid_pid indicates who sent the signal, and 3253 is the bash process (the parent process of the nginx process).

Next, look at the output of the terminal window attached to the bash process:
Insert image description here

Figure 2.4.4 The strace tool attached to the bash process has output

The information shown in Figure 2.4.4 is a bit complicated. Try to find useful information (kill here means sending a signal).

(1) The line starting with "kill(-23099, SIGHUP)", the process group (PGRP) ID of the nginx process is 23099, so this line means sending a signal to the process group where the absolute value of this number is located (if after kill A negative value generally means sending a signal to a process group), that is to say, all processes with the process group ID of 23099 will receive the SIGHUP signal.

(2) In the line of kill(3253, SIGHUP), 3253 is the PID of the bash process itself. When bash receives the SIGHUP signal for the first time, it first sends the signal to other processes in the session (not only the 23099 process group above) process, if there are other process groups, other process groups will also receive the SIGHUP signal (as long as the session IDs of these processes are the same), and then send the SIGHUP command to themselves again to kill themselves. The "sid_pid=3253" in the next line also It means you killed yourself

2.5 How to prevent the process from exiting when the terminal is closed

When the terminal is closed, the nginx process running on the terminal exits. The problem to be solved now is how to prevent the nginx process from exiting when the terminal is closed. Imagine if the nginx process intercepts the SIGHUP signal, is it possible?

2.5.1 nginx process intercepts SIGHUP signal

Modify nginx.c. Signal related content will be discussed later. Here is a small piece of code to ignore the signal. After receiving the SIGHUP signal, the operating system ends the nginx process by default. Now by modifying the code to tell the operating system to ignore the signal, the operating system will not perform the default processing behavior (will not end the process).

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *const *argv)
{
    
    
        printf("hello nginx\n");
        //系统函数,设置收到某个信号时的处理程序(用哪个函数来处理)
		signal(SIGHUP, SIG_IGN); //SIG_ING:代表我要求忽略该信号,请求操作系统不要执行默认的
							     //该信号处理动作(不要把本进程杀掉)。
        for(;;)
        {
    
    
                sleep(1);
                printf("休息1s\n");
        }
        printf("程序退出!再见!\n");
}

At this point, it is compiled and executed, as shown in the figure:
Insert image description here

Figure 2.5.1.1 State before strace tool output

After closing the bash parent process where the nginc process is located, we found that the 6408 bash process was gone, but the nginx process was still there, as shown in the figure:

Insert image description here

Figure 2.5.1.2 Status after strace tool output after closing the bash parent process where the nginc process is located

nginx still exists, but its TT (terminal) column display changes to "?", which means there is no corresponding terminal, and its PPID (parent process ID) becomes 1, which is the ancestor process introduced earlier. The PID (process ID) of init. Originally, the parent process of the nginx process was bash, but bash was terminated and the nginx process became an orphan process. This orphan process was adopted by the init process.

2.5.2 The nginx process and the bash process are in different sessions (different session IDs)

This involves calling the system function setid. This function is used to establish a new session. Modify the nginx.c code as follows:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *const *argv)
{
    
    
        printf("hello nginx\n");
        pid_t pid;
		
		pid = fork();//系统函数,用来创建新进程,后续会继续讲解,子进程会从这句fork调用之后开始
					 //执行,原来的父进程也会接着往下执行
					 //为什么调用fork()函数,而不直接创建会话?是因为主进程是进程组的组长,不允许调用setsid来建立会话
		printf("pid = %d \n", pid);
		if(pid < 0){
    
    
			printf("fork进程出错!\n");
		}else if(pid == 0){
    
    
			//若执行的是子进程,则该条件就会满足
			printf("子进程开始执行!\n");
			//创建新的session
			setsid();
			for(;;)
        	{
    
    
                sleep(1);
                printf("休息1s\n");
        	}
			return 0;
		}else{
    
    
			//父进程才会走到这里
			for(;;)
        	{
    
    
                sleep(1);
                printf("休息1s\n");
       		}
       		return 0;
		}
        printf("程序退出!再见!\n");
        return 0;
}

Here, fork is called to create a child process (after the child process is successfully created, it will run in parallel with the parent process), and then setsid is called in the child process.

At this time, a terminal window compiles, links and runs nginx. As shown in the figure, you can see that both the parent process and the child process are running.
Insert image description here

Figure 2.5.2.1 Recompile, link and execute nginx.c. At this time, the parent process and the child process execute in parallel.

It can be clearly seen that the parent process ID (PID) of the nginx process with PID 16658 is 16657, but the SIDs of the two processes 16658 and 16657 are not the same. You can also find that the child process created by calling the fork function has no associated terminal (the TT/TTY column is displayed as "?").

Now, disconnect the terminal that is displaying nginx execution results and look at the information again:
Insert image description here

Figure 2.5.2.2 Status after strace tool output after closing the bash parent process where the nginc process is located

It can be found that the bash of PID 15806 is gone, and the parent process with PID 16657 is gone, but the child process with PID 166658 is still there. The child process became an orphan process and was adopted by the ancestor init, so the PPID of the child process becomes 1.

2.5.3 Directly use the setsid command

setsid is not only a function (can be used in code), but also a command (can be used in the command line). This command is used to start a process, and can make the started process in a new session, so that the process will not exit after the terminal is closed.

Now, we "kill 166658" to kill the remaining nginx and restore the code:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *const *argv)
{
    
    
        printf("hello nginx\n");
        for(;;)
        {
    
    
                sleep(1);
                printf("休息1s\n");
        }
        printf("程序退出!再见!\n");
        
}

Compile again. gcc -o nginx nginx.c
Execute the command in one terminal window: Execute the command in another terminal window:setsid ./nginx
ps -ef | grep -E "nginx|PID|bash"

Insert image description here

Figure 2.5.3.1 Execution after running setsid ./nginx command

Then we close the nginx terminal and the nginx process still exists:
Insert image description here

Figure 2.5.3.2 Close the nginx terminal and display the execution status of the terminal process

It can be seen that it still exists after closing.

2.5.4 Directly use the nohup command (no hang up does not hang up)

Does this command sound familiar? We introduced a terminal disconnect signal (SIGHUP) earlier, which looks very similar to this command, both are hup. Yes, the program started using the nohup command will ignore (SIGHUP signal), which is the same as ignoring the SIGHUP signal when writing a program.

The nohup command is a little different. Let’s take a look at the execution program:
nohup ./nginx

The result is as shown below:
Insert image description here

Figure 2.5.4.1 Use the nohup command to start an executable program

It can be found that the content originally output on the screen is no longer output, and the cursor stops on the screen. This is a characteristic of the nohup command. This command will redirect the output to the nohup.out file in the current directory. The program needs to be executed for 10 to 20 seconds to find that the size of nohup has changed (it has become greater than 0). Therefore, the output program execution result of this nohup file is not output in real time, but with a certain delay.

Take a look at the current directory structure:
Insert image description here

Figure 2.5.4.2 View the size of the output file nohup.out of the nohup command

View current process information:
Insert image description here

Figure 2.5.4.3 View current nginx process information

After closing the nginx terminal, view the current process information:
Insert image description here

Figure 2.5.4.4 After closing the nginx terminal, view the current process information

nginx still exists, the PPID has become 1, and the child process has become an orphan process and was adopted by the ancestor init.

2.6 Simple understanding of background execution (running)

Commands executed (run) in the background:
./nginx &

Insert image description here

Figure 2.6.1 Use "&" to execute the program in the background

At this time, the program is executed in the background (directly entering ./nginx execution mode can be understood as running in the foreground).

So, what is the difference between a program running in the background and a program running in the foreground?

(1) If the program is executed in the foreground and the ls command is entered in the terminal, the directory cannot be listed; when the program is executed in the foreground, the terminal can only wait for the program pointer to be completed before continuing to execute other programs.
(2) If the program is executed in the foreground, pressing the Ctl + C key combination can stop the execution of the process; if the program is executed in the background, pressing the Ctl + C key combination cannot stop the execution of the process.
(3) You can switch the process executing in the foreground to the foreground by using the fg command: The nginx process is switched to the foreground. At this time, press the Ctl + C key combination to stop the process. (4) If you disconnect the terminal, you will find that even if nignx is a background process, it has been closed (exited).
fg

Guess you like

Origin blog.csdn.net/weixin_30197685/article/details/131266761