Outline
- 1.进程、进程组、会话、控制终端
- 2.守护进程
- 3.例子
================================================================================================
1. 进程、进程组、会话、控制终端在讲述守护进程之前,必须搞明白为什么需要守护进程,那么以上几个名词之间的关系必须搞清楚。进程组的概念就是将一些进程编为一个组,每个进程组有一个进程组长,其特征是pid等于pgid。子进程默认会继承父进程的pgid。父进程可以对其子进程调用setpgid函数更改其pgid值。子进程在exec以后,父进程就不能再改变其pgid了。
- #include <unistd.h>
-
int setpgid(pid_t pid, pid_t pgid);
会话由前台进程组(至多1个)、后台进程组和登录shell进程组成,每个会话有一个控制终端(如串口终端、telnet伪终端等),控制终端会将SIGINT/SIGQUIT信号发送给前台进程组的每一个进程,同时若终端被断开连接,会话首进程(gettty -> setsid -> exec -> shell)将会收到SIGHUP信号。
进程调用setsid可以新建一个会话:
- #include <unistd.h>
-
pid_t setsid(void);
如果调用此函数的进程不是一个进程组长,则此函数就会创建一个新会话,结果将发生下面3件事:
a)该进程变为会话首进程,此时该进程是新会话中唯一的进程。
b)该进程成为一个新进程组的组长进程,ppgid是调用该函数的进程的pid。
c)该进程没有控制终端,加入在setsid之前有,则这种联系将被断开。
2. 守护进程
使用守护进程的主要目的有两个:
a)在系统启动时启动,在系统结束时结束
b)运行期间不受控制终端干扰(如之前提到的几个信号)
简单的说,由于一般进程都由控制终端启动,即使放到后台也会收到信号,因此希望建立一种守护进程,专心的完成它的工作不受外界干扰。
主要步骤:fork -> setsid -> fork(opt)
其中第二个fork是由于在某些系统(如SVR)上,由于第一次fork以后得到的将是一个会话首进程,可能会再次获得某个控制终端,第二次fork以后,由于不再是会话首进程,则绝对不会拥有一个控制终端。
当然这些步骤只是保证了与控制终端断开联系,一个守护进程还需要具备其他一些要素,完整创建规则如下:
a)将umask设置为0,防止从继承父进程得来的umask影响后续操作
b)fork,父进程exit
c)子进程setsid
d)fork (opt)
e)将当前工作目录切换到根目录
f)关闭不需要的文件描述符
g)将标准文件描述符重定向到/dev/null
3.例子
TODO..
阅读(1660) | 评论(0) | 转发(0) |