文章目录
- 前言
- 一、什么是守护进程
- 二、如何创建一个守护进程
- 2.1 守护进程的编程步骤
- 总结
前言
主要解决以下问题:
- 什么是守护进程
- 守护进程的特点
- 如何将进程变为一个守护进程
一、什么是守护进程
守护进程是具备以下特点的进程:
- 生命周期很长,通常一个daemon程序从系统启动被创建到系统关闭而终结。
- 它在后台运行不拥有任何控制终端,因为控制终端的缺失,内核不会再为dammon任何任务控制的信号以及终端相关的信号(SIGTOP,SIGINT,SIGHUP)
- 守护进程就是一种特殊的孤儿进程,这种孤儿进程脱离终端,以防任何控制信号,以及终端相关的信号影响其运行。
- 任何信息都不会显示在控制终端。
二、如何创建一个守护进程
某个进程如果不想被用户,终端或者其他变化受到影响,那必须把这个进程变成守护进程。
2.1 守护进程的编程步骤
- 屏蔽一些控制终端的控制信号(SIGHUP,SIGINT,SIGSTOP,SIGCNT,SIGTOU)
- 执行一个fork(),之后父进程退出,子进程继续执行,子进程成为init的子进程,之所以要这样做的原因是:
- 如果daemon是从命令行终端执行,那么如果终端检测到父进程退出,会重新显示一个提示符,而子进程运行在后台中
- 子进程被确保不会成为进程组的首进程。因为子进程从父进程那里继承了进程组ID,并且拥有一个自己的唯一ID,这个进程ID与继承来的进程组ID不一样,这样子进程可以将自己重新设置为一个新的会话,成为新会话的首进程。
- 脱离控制终端、登录会话和进程组
子进程调用setsid(),使自己成为新会话的首进程,这样可以释放与原控制终端会话进程组的所有联系。 - 禁止进程重新打开终端
现在进程已经成为新的会话的进程组首进程,还是可以重新打开一个新的终端的,那么就要确保进程不会成为控制终端进程,
- 在所有可能应用到一个终端设备上的open()调用中指定O_NOCTTY标识。
- 在setsid()之后重新调用fork(),再创建一个孙子进程,确保孙进程继续执行,孙进程不是会话首进程,禁止了重新打开终端。
- 清除进程的umask
进程从父进程那里继承来的文件掩码可能会影响daemon的对文件的创建。 - 修改进程的当前工作目录
通常会改为根目录(/),这样做是有意义的,因为daemon通常会运行至系统关闭。那么进程运行的文件系统不会被卸载,通常将工作目录改为完成任务所在的目录,只要包含这个目录的文件系统永远不会被卸载即可。 - 关闭daemon从父进程继承而来的文件描述符。
- 重定向文件描述符0,1,2
daemon通常会打开/dev/null,使用dup2,使所有的文件描述符指向这个设备,原因有两个:
- 确保当daemon调用了在这些文件描述符上操作的I/O库函数时不会出现出乎意料的失败。
- 防止daemon后面调用1或者2打开一个文件的情况。
总结
针对防止自己的Linux进程被杀死的解决办法