如何让程序真正地在后台运行?

如何实现一个守护进程?如何让程序在后台运行?这是后台开发面试常问的一道题,那么守护进程到底是什么?又该如何实现?

守护进程

守护进程通常生存期长,很多是在系统启动时启动,系统退出时才关闭。它们的特点通常没有控制终端,后台运行。有人可能会会心一笑,后台运行程序,我知道呀。还有两种方式呢

 

 看,多么简单。但是运行之后,你试着关闭当前终端,你会发现程序会停止运行,因为一旦关闭终端,程序会收到一个信号SIGHUP,而收到该信号默认的动作就是程序退出。没关系啊,我还有招:

 

 我使用nohup命令总可以了吧?挺好的,nohup会忽略SIGHUP命令,并有了&的加持,即便终端关了,也能继续执行。但它的终端输出还会记录默认还在nohup.out文件中,同时,如果将huponexit关闭,它同样难逃命运:

 

 一旦终端退出(ctrl+D)后,nohup也救不了。下面要介绍的守护进程一一种完全脱离终端,有着自己的会话。
如果你在你的Linux系统中执行下面的命令:

 

 就会发现一些进程的tty列是?,当然这并不是说明它们是守护进程,而那些用[]括起来的,是内核守护进程想象一下,如果没有任何人登录的服务器上面的运行程序,难道每次执行的时候都要使用nuhup+&?况且,一旦系统的huponexit选项是打开的,这种方式仍然无法避免终端关闭程序就退出的命运!那么就需要实现用户守护进程了,或者说daemon化。

如何实现

其实现过程基本遵循以下原则:

  • 调用umask设置文件模式,通常设置为0。为了便于后续创建文件,不使用继承而来的父进程的设置,需要设置新的权限掩码。
  • 调用fork,创建子进程,并且父进程退出
  • 调用setdid创建新的会话(一个或多个进程组的集合),由于当前进程不是一个进程组的组长,因此会创建一个新的会话,却成为组长进程,同时没有控制终端。
  • 将当前工作目录切换为根目录。同样的,其工作目录可能是从父进程继承而来的,可以自己另立山头。
  • 关闭不需要的文件描述符。同样的,可能从父进程继承了一些打开的文件描述符,而这些描述符可能再也不需要,因此可以关闭。
  • 重定向标准输出,标准输入和标准错误到/dev/null
  • 实际上,从上面的描述可以发现,这些规则都有几乎相同的目标,那就是不想成为富二代,摆脱父亲的控制。
    • 重新设置权限掩码,避免受父进程影响
    • 创建新的会话,脱离终端
    • 使用新的工作目录
    • 关闭不需要的文件描述符
    • 关闭标准输入,标准输出和标准错误
    所以通过这些也可以明白,有些规则并不是完全强制的,可根据实际程序的情况进行设置,不过按照常规做法是一个比较好的选择。

具体实现

参考代码如下:

如何让程序真正地在后台运行?_第1张图片

 

 如何让程序真正地在后台运行?_第2张图片

 

 编译运行,你就会发现,它已经可以欢脱地运行啦。

实际实现

实际上,已经有一个接口可以帮我们做这些事情:

 

 即daemon函数,它有两个参数

  • nochdir 为0时,表示修改其根目录为/,否则不变
  • noclose,为0时,表示将标准输入,标准输出,标准错误重定向到/dev/null。

简单例子:

如何让程序真正地在后台运行?_第3张图片

 

 

总结

以上就进程后台运行以及是守护进程实现的介绍,关键点有

  • 创建子进程,父进程退出
  • 创建新的会话,脱离终端

附上daemon的源码:

如何让程序真正地在后台运行?_第4张图片

我是一名java程序员,更多的java经验技术分析可以来我的编程技术讨论扣峮1080621881 ,不过你是零基础还是刚入门,你都可以来,有很多适合刚入门的伙伴学习的资料分析详解。

你可能感兴趣的:(如何让程序真正地在后台运行?)