PHP 创建守护进程进程根据状态可以分为三种进程,守护进程,僵尸进程,孤儿进程。今天我们着重来分析下守护进程。

简介

守护进程 (daemon) 是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。

创建步骤

创建子进程,终止父进程

由于守护进程是脱离控制终端的,因此首先创建子进程,终止父进程,使得程序在shell 终端里造成一个已经运行完毕的假象。之后所有的工作都在子进程中完成,而用户在 shell 终端里则可以执行其他的命令,从而使得程序以僵尸进程形式运行,在形式 上做到了与控制终端的脱离。

在子进程中创建新会话

这个步骤是创建守护进程中最重要的一步,在这里使用的是系统函数setsid。setsid 函数用于创建一个新的会话,并担任该会话组的组长。调用 setsid 的三个作用:让进程摆脱原会话的控制、让进程摆脱原进程组的控制和让进程摆脱原控制终端的控制。

在调用 fork 函数时,子进程全盘拷贝父进程的会话期 (session,是一个或多个进程组的集合)、进程组、控制终端等,虽然父进程退出了,但原先的会话期、进程组、控制终端等并没有改变,因此,那还不是真正意义上使两者独立开来。setsid 函数能够使进程完全独立出来,从而脱离所有其他进程的控制。

改变工作目录

使用fork 创建的子进程也继承了父进程的当前工作目录。由于在进程运行过程中,当前目录所在的文件系统不能卸载,因此,把当前工作目录换成其他的路径,如 “/” 或 “/tmp” 等。改变工作目录的常见函数是 chdir。

重设文件创建掩码

文件创建掩码是指屏蔽掉文件创建时的对应位。由于使用fork 函数新建的子进程继承了父进程的文件创建掩码,这就给该子进程使用文件带来了诸多的麻烦。因此,把文件创建掩码设置为 0,可以大大增强该守护进程的灵活性。设置文件创建掩码的函数是 umask,通常的使用方法为 umask (0)。

关闭文件描述符

用fork 新建的子进程会从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远不会被守护进程读或写,但它们一样消耗系统资源,可能导致所在的文件系统无法卸载。

直接上代码

注:运行环境是 linux 系统,并且要在 cli 模式下运行。

文件名:deamon.php

/**

* User: streetlamp

* Date: 2019/1/9

* Time: 15:14

*/

class Deamon{

protected $_pidFile;

public function __construct(){

$this->_pidFile = '/var/www/html/queue/public/pid.log';

$this->_checkPcntl();

}

/**

* 创建守护进程核心函数

* @return string|void

*/

private function _demonize(){

if (php_sapi_name() != 'cli') {

die('Should run in CLI');

}

//创建子进程

$pid = pcntl_fork();

if ($pid == -1) {

return 'fork faile';

} elseif ($pid) {

//终止父进程

exit('parent process');

}

//在子进程中创建新的会话

if (posix_setsid() === -1) {

die('Could not detach');

}

//改变工作目录

chdir('/');

//重设文件创建的掩码

umask(0);

$fp = fopen($this->_pidFile, 'w') or die("Can't create pid file");

//把当前进程的id写入到文件中

fwrite($fp, posix_getpid());

fclose($fp);

//关闭文件描述符

fclose(STDIN);

fclose(STDOUT);

fclose(STDERR);

//运行守护进程的逻辑

$this->job();

return;

}

/**

* 守护进程的任务

*/

private function job(){

//TODO 你的守护经常需要执行的任务

while (true) {

file_put_contents('/var/www/html/queue/public/job.log', 'job' . PHP_EOL, FILE_APPEND);

sleep(5);

}

}

/**

* 获取守护进程的id

* @return int

*/

private function _getPid(){

//判断存放守护进程id的文件是否存在

if (!file_exists($this->_pidFile)) {

return 0;

}

$pid = intval(file_get_contents($this->_pidFile));

if (posix_kill($pid, SIG_DFL)) {//判断该进程是否正常运行中

return $pid;

} else {

unlink($this->_pidFile);

return 0;

}

}

/**

* 判断pcntl拓展

*/

private function _checkPcntl(){

!function_exists('pcntl_signal') && die('Error:Need PHP Pcntl extension!');

}

private function _message($message){

printf("%s %d %d %s" . PHP_EOL, date("Y-m-d H:i:s"), posix_getpid(), posix_getppid(), $message);

}

/**

* 开启守护进程

*/

private function start(){

if ($this->_getPid() > 0) {

$this->_message('Running');

} else {

$this->_demonize();

$this->_message('Start');

}

}

/**

* 停止守护进程

*/

private function stop(){

$pid = $this->_getPid();

if ($pid > 0) {

//通过向进程id发送终止信号来停止进程

posix_kill($pid, SIGTERM);

unlink($this->_pidFile);

echo 'Stoped' . PHP_EOL;

} else {

echo "Not Running" . PHP_EOL;

}

}

private function status(){

if ($this->_getPid() > 0) {

$this->_message('Is Running');

} else {

echo 'Not Running' . PHP_EOL;

}

}

public function run($argv){

$param = is_array($argv) && count($argv) == 2 ? $argv[1] : null;

switch ($param) {

case 'start':

$this->start();

break;

case 'stop':

$this->stop();

break;

case 'status':

$this->status();

break;

default:

echo "Argv start|stop|status " . PHP_EOL;

break;

}

}

}

$deamon = new \Deamon();

$deamon->run($argv);复制代码

运行方式开启守护进程:php demon.php start

停止守护进程:php demon.php stop

查看守护进程的状态:php demon.php status

php 如何守护进程_PHP 编写守护进程相关推荐

  1. Linux 守护进程,编写(转载)

    设置守护进程过程: 1.创建子进程,父进程退出 2.在子进程中创建新会话 3.改变当前目录为根目录 4.重设文件权限掩码 5.关闭文件描述符 *6.守护进程里,忽略SIGCHLD信号 (即使fork两 ...

  2. python3 编写守护进程程序思路

    1. fork子进程,父进程退出 通常,我们执行服务端程序的时候都会通过终端连接到服务器,成功连接后会加载shell环境,终端和shell都是进程,shell进程是终端进程的子进程,通过ps命令可以很 ...

  3. php 如何守护进程_PHP 如何实现守护进程

    PHP 如何实现守护进程 发布时间:2020-07-11 15:29:31 来源:亿速云 阅读:58 作者:Leah PHP 如何实现守护进程?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望 ...

  4. linux编写守护进程

    1.实验目的 通过编写一个完整的守护进程,使读者掌握守护进程编写和调试的方法,并且进一步熟悉如何编写多进程 程序. 2.实验内容 在该实验中,读者首先建立起一个守护进程,然后在该守护进程中新建一个子进 ...

  5. linux守护进程以及如何编写守护进程程序

    守护进程 理论 「守护进程」是 Linux 的一种长期运行的后台服务进程,也有人称它为「精灵进程」.我们常见的 httpd.named.sshd 等服务都是以守护进程 Daemon 方式运行的,通常服 ...

  6. Linux守护进程编程编写,linux守护进程编程实例

    /* *功能:创建一个守护进程,监视系统所有运行的进程 *时间:2013.4.14 */ #include #include #include #include #include #include # ...

  7. 小何讲进程: 编写Linux守护进程方法详解

    守护进程概述 守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程. 它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些事件的发生. 守护进程常常在 ...

  8. 守护进程和inetd守护进程

    一.守护进程介绍 守护进程是在后台运行且不与任何控制终端相关联的进程.通常由系统初始化脚本启动,当然也可以在shell提示符下用命令行启动,不过这种守护进程必须亲自脱离于控制终端的关联. 守护进程的启 ...

  9. python守护进程_Python实现守护进程

    考虑如下场景:你编写了一个python服务程序,并且在命令行下启动,而你的命令行会话又被终端所控制,python服务成了终端程序的一个子进程.因此如果你关闭了终端,这个命令行程序也会随之关闭. 要使你 ...

最新文章

  1. Linux: TLB 查询流程
  2. 支付接口教程,详解支付宝接口(二)
  3. 实例浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO
  4. python django restful框架_python+django+rest框架配置创建方法
  5. linux x64下安装oracle 11g
  6. 浅析Microsoft .net PetShop程序中的购物车和订单处理模块(Profile技术,异步MSMQ消息)
  7. ansys 命令流学习
  8. 5款开源BI系统倾力推荐,企业信息化的利器
  9. 银联 php hex2bin,银联支付
  10. 【转】Unity5 新AssetBundle打包方式 BuildPipeline.BuildAssetBundles
  11. linux ls和cd命令详解,Linux基础cd、pwd和ls命令
  12. python 遗传算法多目标优化_NSGA2 遗传算法解决多目标优化
  13. java展示树形结构的两种方式
  14. 数值分析之牛顿拉夫森迭代(牛顿法)
  15. 在20岁到30岁的约定
  16. 无线网突然提示IP地址冲突,无法连接
  17. 链家房屋数据分析实战
  18. 运算符 狂神说Java随堂笔记
  19. MT6589 SCH_PCB_check_list完整资料下载
  20. 神经网络常见的激活函数汇总

热门文章

  1. 多个ai文件合并成pdf_ai导出多个单个画板的AI文件,类似PDF拆分然后能同时输出多个单PDF文件...
  2. ASEMI代理ADI亚德诺ADXL345BCCZ-RL7车规级芯片
  3. php 人民币格式化,php人民币格式化,php分割字符串
  4. android之Fresco框架(一)--Fresco基本使用
  5. BroadCast Receiver(广播)详解
  6. 英特尔的Movidius AI加速技术适用于mini-PCIe版本,旨在加速神经网络
  7. idea浅色主题及代码字体颜色配置
  8. 六、Abp Vnext 中Efcore的多模块关联查询
  9. 中国统计年鉴2018
  10. Ubuntu server 14.04 双网卡上网设置