概述
守护进程(daemon)听着像一个ghost,无处不在而又默默存在。其实还真是这样一个存在。 它默默运行在系统的后台并具有以下特征:
- 父进程是init(1号进程)
- 没有和任何控制终端关联,所以也不会收到诸如SIGINT( 信号名称,Ctrl-C会产生这个信号 )、SIGTSTP( TSTP的意思是tty stop,即在control terminal上输入了ctl-z代表的suspend键,会产生这个信号,继而发送给进程)等信号
The Implementation of A Daemon
在Linux中,每个从终端开始运行的进程都会依附于这个终端,这个终端是这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。 但是守护进程为了实现不受某些参数的影响,不和终端关联,必须要从这个限制突破出去,成为一个自由的ghost。从被执行开始运转,直到整个系统关闭时才退出。 如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程,脱离于终端并且在后台运行。
接下来就可以用某种方法实现这个过程:
- 创建子进程,父进程退出 由于守护进程是脱离控制终端的,因此,完成第一步后就会在Shell终端里造成一程序已经运行完毕的假象。之后的所有工作都在子进程中完成,而用户在Shell终端里则可以执行其他命令,从而在形式上做到了与控制终端的脱离。 在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程,就会自动由1号进程(init)收养它,这样原先的子进程就会变成init进程的子进程。
- 在子进程中创建新会话 这个步骤是创建守护进程中最重要的一步,在这里使用的是系统函数setsid,在具体介绍setsid之前,首先要了解两个概念:进程组和会话期【2】。 进程组:是一个或多个进程的集合。进程组有进程组ID来唯一标识。除了进程号(PID)之外,进程组ID也是一个进程的必备属性。每个进程组都有一个组长进程,其组长进程的进程号等于进程组ID。且该进程组ID不会因组长进程的退出而受到影响。 会话周期:会话期是一个或多个进程组的集合。通常,一个会话开始与用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。
接下来就可以具体介绍setsid的相关内容: setsid函数用于创建一个新的会话,并担任该会话组的组长。调用setsid有下面的3个作用:
- 让进程摆脱原会话的控制
- 让进程摆脱原进程组的控制
- 让进程摆脱原控制终端的控制
那么,在创建守护进程时为什么要调用setsid函数呢?由于创建守护进程的第一步调用了fork函数来创建子进程,再将父进程退出。由于在调用了 fork函数时,子进程全盘拷贝了父进程的会话期、进程组、控制终端等,虽然父进程退出了,但会话期、进程组、控制终端等并没有改变,因此,还还不是真正意义上的独立开来,而setsid函数能够使进程完全独立出来,从而摆脱其他进程的控制。
setsid命令的一般格式:setsid();
之前parent和child运行在同一个session里,parent是会话(session)的领头进程,parent进程作为会话的领头进程,如果exit结束执行的话,那么子进程会成为孤儿进程,并被init收养。执行setsid()之后,child将重新获得一个新的会话(session)id。这时守护进程能够完全独立出来,从而摆脱其他进程的控制。
现在用守护进程实现一个每隔10s在/tmp/dameon.log中写入一句话的功能,实现代码(damon.c)如下:
Daemon开机自启动实现
首先,将daemon.c编译成名为 simple-daemon 然后,写一个shell脚本daemon-script,编辑需要自启动的 simple-daemon程序的名字和路径
<!-- lang: shell -->
###########################
#start writing the script#
###########################
#source function library
PATH=/bin:/usr/bin:/sbin:/usr/sbin
./lib/lsb/init-functions
PROG="simple-daemon"
PROG_PATH="home/huangyi/MyProgram"
start(){
$PROG_PATH/$PROG
echo "$PROG started"
}
stop(){
echo "begin stop"
killall $PROG
echo "$PROG stopped"
} 再将脚本daemon-script 复制到/etc/init.d/目录下。init进程逐一加载开机启动程序,其实就是运行目录/etc/init.d/里的启动脚本。 最后执行 chkconfig - -add daemon-script 这样就可以和Apache服务器一样开机自启动,并用服务进行管理。
<!-- lang: shell -->
service daemon-script start //启动,系统默认是开启的
service daemon-script stop //停止
service daemon-script restart //重启
Reference
[1].http://blog.csdn.net/jiaxiongxu/article/details/6692541
[2].http://www.informit.com/articles/article.aspx?p=366888&seqNum=8
[3].http://my.oschina.net/u/556678/blog/183780