会话进程组终端 · 守护进程
会话
会话是进程组的集合。
通常一个shell下的所有进程组与shell自身属于同一会话。
通常会话与某个控制终端 ( shell初打开 ) 相关,一个终端至多只能成为一个会话的控制终端。
一旦断开于终端的连接(如关闭终端窗口),控制进程将会收到SIGHUP信号(默认终止进程)。
在任一时点,一个会话总有一个前台进程组,一个会话可以拥有任意数量的后台进程组。
Linux系统编程下p574图
伪终端
伪终端是一对相互连接的虚拟设备。
如telnet、ssh以及X Window系统所提供的终端窗口实现。
SIGHUP
当一个控制进程失去其终端连接之后,内核会向其发送一个SIGHUP信号。
- 终端连接断开 2. 终端窗口被关闭
链式反应
- 控制进程通常是shell,它建立了一个SIGHUP信号处理器,会将SIGHUP信号发送给它创建的各个任务。
- 在终止终端的控制进程时,内核会解除会话中所有进程与该控制终端间的关联关系以及控制终端与该会话的关联关系,并通过向该终端的前台进程组的成员发送SIGHUP来通知它们控制终端的丢失
nohup可以使命令对SIGHUP免疫:将SIGHUP的处理设置伪SIG_IGN
tmux终端复用/会话管理
https://www.cnblogs.com/weiyinfu/p/10463215.html
守护进程
由以上可知,守护进程应当
- 在后台执行 (fork两次,...,父进程为init进程)
- 在新的会话中
- 设置文件权限与工作目录
- 关闭其它文件描述符,将stdin/stdout/stderr重定向至/dev/null
一个daemon通常只有在系统关闭时才会终止。
很多标准的daemon是通过在系统关闭时执行特定的应用程序的脚本来停止的。
而不以这种方式终止的daemon会收到一个 SIGTERM 信号,因为在系统关闭时 init 进程会向所有的子进程发送这个信号。在默认情况下,SIGTERM 会终止 一个进程,如果daemon在终止之前需要做清理工作,那么就需要为这个信号建立一个处理器。这个处理器必须能够快速的完成清理工作,因为init会在发完 SIGTERM 信号的 5 秒后,发送一个 SIGKILL 信号。
使用 SIGHUP 重新初始化一个 daemon
由于很多daemon需要持续运行,因此在设计daemon程序时需要克服一些障碍:
- 通常daemon会在启动时从相关的配置文件中读取操作参数,但有些时候需要在不重启daemon的情况下快速修改这些参数(重新读取配置)
- 一些daemon会产生日志。如果daemon永远不关闭日志的话,那么日志文件就会无限的增长,最终会阻塞文件系统(即使删除了一个文件的文件名,只要有进程还打开这个文件,那么这个文件就会一直存在下去)。这里需要有一个机制来告诉daemon关闭其日志并打开一个新文件,这样就能够在需要的时候轮转日志文件了。(日志切割)
在解决这2个问题的方案是让 daemon 为 SIGHUP 建立一个处理器,并且在收到这个信号的时候采取所需的措施。当控制进程与控制终端断开连接之后会生成 SIGHUP信号。由于 daemon没有控制终端,因此内核永远不会向 daemon 发送这个信号。这样 daemon 就可以使用 SIGHUP 信号来达到目的了。
logrotate可自动旋转daemon的日志文件。