声明:这篇文章是我09年的时候发表在自己之前的BLOG上的,属于原创内容,现在将文章转移到这里。
守护进程也称精灵进程(daemon),是生存期较长的一种进程。它们常常用在系统自举时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。UNIX类操作系统有很多的守护进程,它们执行日常事务活动。
目前有大量的web站点基与PHP开发,业务逻辑都是由PHP来实现,很多时候我们也需要一个PHP的daemon来做一些日常事务,例如我们想每隔一个小时统计一下数据库中的某项数据,每天定期的执行一些备份或则监控任务。这些任务在apache模块的web环境下实现比较困难而且容易引发很多问题。
这里我介绍一款我自己写的PHP5版的daemon类 - KalonDaemon. ^_^ 现在和大家一起分享。
概要:
KalonDaemon是一款PHP5的daemon类,我们在PHP代码中可以直接包含并且使用,KalonDaemon工作在cli sapi下( command line interface),它能把一个普通的PHP进程变成一个守护进程。
使用方式:
在PHP脚本中包含了KalonDaemon设置好参数然后调用start()方法。然后我们在命令行下用PHP cli执行脚本,比如cli sapi路径为 /usr/local/bin/php, 我们编写的程序路径 /home/test/mydaemon.php,那么我们用以下方式运行程序: /usr/local/bin/php /home/test/mydaemon.php 根据需要可以在后面添加别的参数。
工作流程:
KalonDaemon遵循大部分unix类系统下的守护进程编程规则,主要工作流程如下:
1. 调用pcntl_fork,然后使父进程退出(exit).这样做实现如下几点:第一,如果该守护进程是作为一条shell命令启动,那么父进程终止使得 shell认为这条命令已经执行完毕;第二,子进程继承父进程的进程组ID,但是具有一个新的进程ID,这就保证了子进程不是一个进程组的组长,这对于下面要做的posix_setsid调用是必要的前提条件。
2.调用posix_setsid以创建一个新的会话,这样新进程就成为了新会话的首进程,同时是新进程组的组长进程,而且没有控制终端。
3.设置进程信号回调函数,方便我们用其它进程对守护进程进行控制。
以下是mydaemon.php的源码:
在命令行下执行:
/path/to/phpcli/php mydaemon.php start
输出如下信息:
Daemon started with pid 8976...
running.
说明守护进程已经开始运行,进程号为8976,当然一般情况进程号每次都会不一样。
由于mydaemon.php中有一个死循环,每次循环会睡眠1000秒,所以进程永远不会终止。
mydaemon.php中为守护进程注册了两个信号句柄,信号SIGUSR1对应函数myHandler1(), 信号SIGUSR2对应myHandler2(),我们可以通过kill命令给进程发送这两个信号来唤醒进程。
kill -SIGUSR2 8976
输出信息如下:
This handler2 works.
running.
说明睡眠中的进程被唤醒,并且执行了myHandler2()函数,然后再次进入了循环。
当我们需要终止守护进程的时候,可以用以下命令:
/path/to/phpcli/php mydaemon.php stop
输出信息如下:
Daemon stopped with pid 8976...
这样守护进程就终止了。
这样的特性可以在某些应用场景非常有用,比如服务器在接受到一些上传的数据之后,需要唤醒守护进程来处理这些数据。守护进程可以长期出去睡眠状态等待,当数据到来之后,发送信号唤醒守护进程,守护进程马上开始处理这些数据。这样要比定期的轮询效率高很多,而且不会有延迟现象。
KalonDaemon.php