终端和进程的关系
【终端与bash进程】
- 使用ps -ef | grep bash命令查看 bash 进程
- 再开一个终端连接,再次查看发现有两个bash进程
- pts(虚拟终端),每连接一个虚拟终端到linux操作系统,就会出现 一个bash进程(shell[壳]),黑窗口,用于解释用户输入的命令,bash = shell = 命令行解释器
【终端上的开启进程】
- ps -la可以查看终端上的进程(包括其他终端上开启的进程)
- 如果终端退出,这个终端上运行的进程nginx也退出了
【进程关系进一步分析】
- 每个进程还属于一个进程组:一个或者多个进程的集合,每个进程组有一个唯一的进程组ID,可以调用系统 函数来创建进程组、加入进程组
- “会话”(session):是一个或者多个进程组的集合
- 一般,只要不进行特殊的系统函数调用,一个bash(shell)上边运行的所有程序都属于一个会话,而这个会话有一个session leader;
- 那么这个bash(shell)通常就是session leader; 你可以调用系统功函数创建新的session。
- 使用命令查看:ps -eo pid,ppid,sid,tty,pgrp,comm | grep -E 'bash|PID|nginx'
- a)如果我 xshell终端要断开的话,系统就会发送SIGHUP信号(终端断开信号),给session leader,也就是这个bash进程
- b)bash进程 收到 SIGHUP信号后,bash会把这个信号发送给session里边的所有进程,收到这个SIGHUP信号的进程的缺省动作就是退出。
【strace工具的使用】
- linux下调试分析诊断工具:可以跟踪程序执行时进程的系统调用以及所收到的信号。
- 跟踪nginx进程 : sudo strace -e trace=signal -p 进程id
- kill(4294965937, SIGHUP) :发送信号SIGHUP给这个 -1359的绝对值所在的进程组,所以nginx进程就收到了SIGHUP信号
- 综合来讲,这个bash先发送SIGHUP给 同一个session里边的所有进程,然后再发送SIGHUP给自己。
【终端关闭时如何让进程不退出】
【方法1】nginx进程拦截(忽略)SIGHUP(nginx收到这个信号并告诉操作系统不想被干掉,请不要处理)信号。
#include <stdio.h> #include <unistd.h> #include <signal.h> int main(int argc, char *const *argv) { //系统函数,设置某个信号来的时候处理程序(用哪个函数处理) signal(SIGHUP,SIG_IGN); //SIG_IGN标志:我要求忽略这个信号,请操作系统不要用缺省的处理方式来对待我(不要把我干掉); for(;;) { sleep(1); //休息1秒 printf("父进程休息1秒\n"); } return 0; }
- 使用命令查看:ps -eo pid,ppid,sid,tty,pgrp,comm | grep -E 'bash|PID|nginx'
- 关闭终端
- nginx成为孤儿进程。
【方法2】nginx进程和bash进程不再同一个session里(setsid函数不适合进程组组长调用)
#include <stdio.h> #include <unistd.h> int main(int argc, char *const *argv) { pid_t pid; pid = fork(); //系统函数,用来创建新进程。子进程会从fork()调用之后开始执行 if(pid < 0) { printf("fork()进程出错!\n"); } else if(pid == 0) { //子进程这个条件会满足 printf("子进程开始执行!\n"); setsid(); //新建立一个不同的session,但是进程组组长调用setsid()是无效的 for(;;) { sleep(1); //休息1秒 printf("子进程休息1秒\n"); } return 0; } else { //父进程会走到这里 for(;;) { sleep(1); //休息1秒 printf("父进程休息1秒\n"); } return 0; } return 0; }
- 关闭终端前:
- 关闭终端后:
【方法3】启动一个进程,而且能够使启动的进程在一个新的session中,这样的话,终端关闭时该进程就不会退出
- 如:setsid ./nginx
- 关闭终端后
【方法4】nohup(no hang up不要挂断),用该命令启动的进程跟上边忽略掉SIGHUP信号,道理相同
- 如:nohup ./nginx
- 该命令会把屏幕输出重新定位到当前目录的nohup.out。
【后台执行】
- 后台执行,执行这个程序的同时,在终端能够干其他事情。如果不用后台执行,那么执行这个程序后的终端就只能等这个程序完成后才能继续执行其他的操作(fg切换到前台)。