守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种颇有用的进程。php也能够实现守护进程的功能。php
最近要开发一个 Agent,由于和 webserver 一块儿开发,因此 Agent也用PHP 开发。web
功能需求:编程
(1)需监听端口,接收控制器发来的任务消息;session
(2)根据任务消息,启动执行任务,并监控任务状态;框架
(3)将任务运行结果反馈给控制器;函数
开始使用 workerman 框架,可是发现框架虽好,但也有不少限制。code
一、基本概念server
进程:每一个进程都有一个父进程,子进程退出,父进程能获得子进程退出的状态。继承
进程组:每一个进程都属于一个进程组,每一个进程组都有一个进程组号,该号等于该进程组组长的PID进程
二、守护进程编程要点
1. 在后台运行。
为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 if($pid=pcntl_fork()) exit(0);//是父进程,结束父进程,子进程继续
2. 脱离控制终端,登陆会话和进程组
有必要先介绍一下Linux中的进程与控制终端,登陆会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登陆会话能够包含多个进程组。这些进程组共享一个控制终端。这个控制终端一般是建立进程的登陆终 端。 控制终端,登陆会话和进程组一般是从父进程继承下来的。咱们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: posix_setsid();
说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登陆会话和进程组脱离。因为会话过程对控制终端的独占性,进程同时与控制终端脱离。
3. 重设文件建立掩模
进程从建立它的父进程那里继承了文件建立掩模。它可能修改守护进程所建立的文件的存取位。为防止这一点,将文件建立掩模清除:umask(0);
umask(0)就是设置容许当前进程建立文件或者目录最大可操做的权限,好比这里设置为0,它的意思就是0取反再建立文件时权限相与,也就是:(~0) & mode 等于八进制的值0777 & mode了,这样就是给后面的代码调用函数mkdir给出最大的权限,避免了建立目录或文件的权限不肯定性。
<?php function daemonize() { umask(0); $pid = pcntl_fork(); if (-1 === $pid) { throw new Exception('fork fail'); } elseif ($pid > 0) { exit(0); } //Make the current process a session leader. if (-1 === posix_setsid()) { throw new Exception("setsid fail"); } // Fork again avoid SVR4 system regain the control of terminal. $pid = pcntl_fork(); if (-1 === $pid) { throw new Exception("fork fail"); } elseif (0 !== $pid) { exit(0); } }