文章目录

  • 前言
  • 一、什么是守护进程
  • 二、如何创建一个守护进程
  • 2.1 守护进程的编程步骤
  • 总结



前言

主要解决以下问题:

  1. 什么是守护进程
  2. 守护进程的特点
  3. 如何将进程变为一个守护进程

一、什么是守护进程

守护进程是具备以下特点的进程:

  • 生命周期很长,通常一个daemon程序从系统启动被创建到系统关闭而终结。
  • 它在后台运行不拥有任何控制终端,因为控制终端的缺失,内核不会再为dammon任何任务控制的信号以及终端相关的信号(SIGTOP,SIGINT,SIGHUP)
  • 守护进程就是一种特殊的孤儿进程,这种孤儿进程脱离终端,以防任何控制信号,以及终端相关的信号影响其运行。
  • 任何信息都不会显示在控制终端。

二、如何创建一个守护进程

某个进程如果不想被用户,终端或者其他变化受到影响,那必须把这个进程变成守护进程。

2.1 守护进程的编程步骤

  1. 屏蔽一些控制终端的控制信号(SIGHUP,SIGINT,SIGSTOP,SIGCNT,SIGTOU)
  2. 执行一个fork(),之后父进程退出,子进程继续执行,子进程成为init的子进程,之所以要这样做的原因是:
  • 如果daemon是从命令行终端执行,那么如果终端检测到父进程退出,会重新显示一个提示符,而子进程运行在后台中
  • 子进程被确保不会成为进程组的首进程。因为子进程从父进程那里继承了进程组ID,并且拥有一个自己的唯一ID,这个进程ID与继承来的进程组ID不一样,这样子进程可以将自己重新设置为一个新的会话,成为新会话的首进程。
  1. 脱离控制终端、登录会话和进程组
    子进程调用setsid(),使自己成为新会话的首进程,这样可以释放与原控制终端会话进程组的所有联系。
  2. 禁止进程重新打开终端
    现在进程已经成为新的会话的进程组首进程,还是可以重新打开一个新的终端的,那么就要确保进程不会成为控制终端进程,
  • 在所有可能应用到一个终端设备上的open()调用中指定O_NOCTTY标识。
  • 在setsid()之后重新调用fork(),再创建一个孙子进程,确保孙进程继续执行,孙进程不是会话首进程,禁止了重新打开终端。
  1. 清除进程的umask
    进程从父进程那里继承来的文件掩码可能会影响daemon的对文件的创建。
  2. 修改进程的当前工作目录
    通常会改为根目录(/),这样做是有意义的,因为daemon通常会运行至系统关闭。那么进程运行的文件系统不会被卸载,通常将工作目录改为完成任务所在的目录,只要包含这个目录的文件系统永远不会被卸载即可。
  3. 关闭daemon从父进程继承而来的文件描述符。
  4. 重定向文件描述符0,1,2
    daemon通常会打开/dev/null,使用dup2,使所有的文件描述符指向这个设备,原因有两个:
  • 确保当daemon调用了在这些文件描述符上操作的I/O库函数时不会出现出乎意料的失败。
  • 防止daemon后面调用1或者2打开一个文件的情况。

总结

针对防止自己的Linux进程被杀死的解决办法