守护进程最大的特点就是不受终端控制,并且在后台运行。linux上很多应用都是以守护进程的方式存在的,比如常用的crond。把应用做成守护进程的好处就是可以脱离终端,不会因为终端的关闭而挂掉,会随着系统的存在而存在。
创建守护进程有以下几个要点:
<1> 创建子进程,杀掉父进程。
这么做主要是为了确保进行操作<2>的进程不是会话组长,因为会话组组长调用setsid会失败。
<2> 调用setsid()
每个进程都属于一个进程组,进程组号就是进程组组长的pid。多个进程组属于一个会话(一次登录形成一个会话),会话独享一个终端。setsid的作用是使调用进程成为新的会话组长和新的进程组组长。这么干是因为现在的进程是fork出来的,那么就继承了父进程的会话和进程组。如果会话关闭,很有可能会给进程组中的每一个进程都发送一个SIGHUP信号来停止进程。所以我们通过setsid来脱离父进程原来的会话和进程组。
<3> 禁止进程重新打开终端
第<2>步之后,进程成为了会话组长,可以申请重新打开一个终端。第<2>步中强调了终端对进程的影响,所以我们应该禁止该进程重新获取一个终端,一般是通过fork,关闭父进程,继续使用子进程,使该进程不再是会话组长。
<4> 关闭文件描述符
进程fork的时候,子进程会拷贝父进程的文件描述符,子进程一般不使用它们。但是如果文件描述符保持打开状态,那么会造成文件系统无法卸下以及一些无法预料的错误。所以我们应该关闭从父进程拷贝到的文件描述符。除了一般的文件描述符,守护进程一般是不与终端交互的,所以STDIN, STDERR, STDOUT都应该被重定向到/dev/null。一般使用dup和dup2来完成。但是如果希望得到守护进程的输出,或者错误输出,则可以使用dup或者dup2将STDERR和STDOUT重定向到特殊的文件。
<5> 切换当前的工作目录
由于进程活动的目录不能被文件系统卸下,但是守护进程一般开启就不会再关闭了,所以它会一直占用着这个目录不让文件系统卸下。所以一般会把守护进程的工作目录切换到永远也不会被文件系统卸下的根目录。
<6> 改变文件掩码
在fork时,子进程不光拷贝了父进程的文件描述符,而且连文件掩码也一块拷贝过来了。如果父进程使用umask设置了一些特殊的权限,那么子进程在创建文件时很可能就会因为设定权限时被拒绝而失败。所以应该使用umask(0)来重置文件掩码。
实现如下:
代码运行结束后,daemon_out.txt 和 daemon_err.txt中有了对应的字符串输出。
原文地址:https://www.cnblogs.com/MyOnlyBook/p/9581748.html