php 多进程 常驻内存,PHP 多进程与信号中断实现多任务常驻内存管理 [Master/Worker 模型]...

本文章基于pcntl扩展做的多进程测试。

进程调度策略

父子进程的调度由操作系统来负责,具体先调度子进程还是父进程由系统的调度算法决定,当然可以在父进程加上延时或是调用进程回收函数pcntl_wait可以先让子进程先运行,进程回收的目的是释放进程创建时占用的内存空间,防止变成僵尸进程。

信号:

信号称为软中断系统或是叫软中断,功能是向进程发送异步事件通知。

信号编号: 【源码基于SIGINT,SIGTERM,SIGUSR1信号,含义请自行查看kill命令手册,不在描述】

linux支持64个,有一半为实时信号,一半为非时实信号,这些信号都有自己的编号和对应的整数值。每个信号的编号含义读者可以参阅linux相关手册【man手册看看就知道了】

信号处理函数:

信号一般会绑定相应的功能,有的是默认动作如SIGKILL,SIGTERM,SIGINT操作默认操作就是干掉进程,当然我们可以重写覆盖掉,就是通过pcntl_signal来覆盖掉。

信号的概念:与硬件中断一个道理,请读者自行参考本人前面撸过的文章或是查看芯片硬件中断原理。

信号的发送:

kill 信号编号 进程 或是按键产品的中断信号或是在源码里可以使用posix_kill等函数。

进程是相互隔离的,拥有自己的堆栈空间,除了一些公用的正文【代码区】,同时也有自己的可执行代码,进程运行时,将占用cpu的资源,其它进程将无权运行,此时其它进程将为阻塞状态【比如前面撸过的tcp服务】,当进程运行结束后【运行到代码的最后一句或是遇到return或是遇到exit退出进程函数或是遇到信号事件时将会退出】让出权限并释放掉内存,其它进程就有机会运行了。

进程拥有的自己进程描述符,其中比较常用的是进程号PID,进程运行时会在系统/proc/PID下生成相应的进程文件,用户可以自行查看。

每个进程都拥有所属的进程组【进程的集合】,多个进程组集合则是一个会话,创建一个会话是通过一个进程进行创建的,并且此进程不可以为组长进程,此进程将成为会话期的会话首进程,也会成为进程组的进程组长,同时将会脱离控制终端,即使之前的进程绑定了控制终端也会脱离【守护进程的创建】。

文件描述权限掩码【权限屏蔽字】:

umask() 你可以在linux运行这个命令,然后创建文件,并查看它的权限【如果你跑完啥也没有发现,说明你还是训练不够^_^】

/**

* Created by PhpStorm.

* User: 1655664358@qq.com

* Date: 2018/3/26

* Time: 14:19

*/

namespace Chen\Worker;

class Server

{

public $workerPids = [];

public $workerJob = [];

public $master_pid_file = "master_pid";

public $state_file = "state_file.txt";

function run()

{

$this->daemon();

$this->worker();

$this->setMasterPid();

$this->installSignal();

$this->showState();

$this->wait();

}

function wait()

{

while (1){

pcntl_signal_dispatch();

$pid = pcntl_wait($status);

if ($pid>0){

unset($this->workerPids[$pid]);

}else{

if (count($this->workerPids)==0){

exit();

}

}

usleep(100000);

}

}

function showState()

{

$state = "\nMaster 信息\n";

$state.=str_pad("master pid",25);

$state.=str_pad("worker num",25);

$state.=str_pad("job pid list",10)."\n";

$state.=str_pad($this->getMasterPid(),25);

$state.=str_pad(count($this->workerPids),25);

$state.=str_pad(implode(",",array_keys($this->workerPids)),10);

echo $state.PHP_EOL;

}

function getMasterPid()

{

if (file_exists($this->master_pid_file)){

return file_get_contents($this->master_pid_file);

}else{

exit("服务未运行\n");

}

}

function setMasterPid()

{

$fp = fopen($this->master_pid_file,"w");

@fwrite($fp,posix_getpid());

@fclose($fp);

}

function daemon()

{

$pid = pcntl_fork();

if ($pid<0){

exit("fork进程失败\n");

}else if ($pid >0){

exit(0);

}else{

umask(0);

$sid = posix_setsid();

if ($sid<0){

exit("创建会话失败\n");

}

$pid = pcntl_fork();

if ($pid<0){

exit("进程创建失败\n");

}else if ($pid >0){

exit(0);

}

//可以关闭标准输入输出错误文件描述符【守护进程不需要】

}

}

function worker()

{

if (count($this->workerJob)==0)exit("没有工作任务\n");

foreach($this->workerJob as $job){

$pid = pcntl_fork();

if ($pid<0){

exit("工作进程创建失败\n");

}else if ($pid==0){

/***************子进程工作范围**********************/

//给子进程安装信号处理程序

$this->workerInstallSignal();

$start_time = time();

while (1){

pcntl_signal_dispatch();

if ((time()-$start_time)>=$job->job_run_time){

break;

}

$job->run(posix_getpid());

}

exit(0);//子进程运行完成后退出

/***************子进程工作范围**********************/

}else{

$this->workerPids[$pid] = $job;

}

}

}

function workerInstallSignal()

{

pcntl_signal(SIGUSR1,[__CLASS__,'workerHandleSignal'],false);

}

function workerHandleSignal($signal)

{

switch ($signal){

case SIGUSR1:

$state = "worker pid=".posix_getpid()."接受了父进程发来的自定义信号\n";

file_put_contents($this->state_file,$state,FILE_APPEND);

break;

}

}

function installSignal()

{

pcntl_signal(SIGINT,[__CLASS__,'handleMasterSignal'],false);

pcntl_signal(SIGTERM,[__CLASS__,'handleMasterSignal'],false);

pcntl_signal(SIGUSR1,[__CLASS__,'handleMasterSignal'],false);

}

function handleMasterSignal($signal)

{

switch ($signal){

case SIGINT:

//主进程接受到中断信号ctrl+c

foreach ($this->workerPids as $pid=>$worker){

posix_kill($pid,SIGINT);//向所有的子进程发出

}

exit("服务平滑停止\n");

break;

case SIGTERM://ctrl+z

foreach ($this->workerPids as $pid=>$worker){

posix_kill($pid,SIGKILL);//向所有的子进程发出

}

exit("服务停止\n");

break;

case SIGUSR1://用户自定义信号

if (file_exists($this->state_file)){

unlink($this->state_file);

}

foreach ($this->workerPids as $pid=>$worker){

posix_kill($pid,SIGUSR1);

}

$state = "master pid\n".$this->getMasterPid()."\n";

while(!file_exists($this->state_file)){

sleep(1);

}

$state.= file_get_contents($this->state_file);

echo $state.PHP_EOL;

break;

}

}

}

/**\

* Created by PhpStorm.\ * User: 1655664358@qq.com

* Date: 2018/3/26\ * Time: 14:37\ */\namespace Chen\Worker;

class Job

{

public $job_run_time = 3600;

function run($pid)

{\sleep(3);

echo "worker pid = $pid job 没事干,就在这里job\n";

}

}

/**

* Created by PhpStorm.\ * User: 1655664358@qq.com

* Date: 2018/3/26\ * Time: 14:37\ */\namespace Chen\Worker;

class Talk

{

public $job_run_time = 3600;

function run($pid)

{\sleep(3);

echo "worker pid = $pid job 没事干,就在这里talk\n";

}

}

/**

* Created by PhpStorm.\ * User: 1655664358@qq.com

* Date: 2018/3/26\ * Time: 15:45\ */

require_once 'vendor/autoload.php';

$process = new \Chen\Worker\Server();

$process->workerJob = [new \Chen\Worker\Talk(),new \Chen\Worker\Job()];

$process->run();

c1e0bf22868c4fa5abd874ad8aae4ed1.png

本作品采用《CC 协议》,转载必须注明作者和本文链接

只会php crud的渣渣

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RPG的错排

RPG的错排 Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 25 Accepted Submission(s) : 14 Problem Description今年暑假杭电ACM集训队第一次组成女生队,其中有一队叫RPG,但做为集训队成员之一的野骆驼竟然不知道…

读取properties

为什么80%的码农都做不了架构师&#xff1f;>>> //db 是文件名为db.properties private static final ResourceBundle bundle ResourceBundle.getBundle("db");public static String getProperties(String key){return bundle.getString(key);} 转载于:…

Java 8新特性(二)

2019独角兽企业重金招聘Python工程师标准>>> 集合类的批处理&#xff1a; Java8除了Lambda表达式外还提供了另一个重要的特性&#xff0c;即集合的批处理操作&#xff0c;集合类的批处理操作API的目的是实现集合类的“内部迭代”&#xff0c;并期望充分利用现代多核…

Python 支付宝支付代码

2019独角兽企业重金招聘Python工程师标准>>> #!/usr/bin/env python # encoding: utf-8Created on 2011-1-5 author: codebackgmail.comimport hashlib import urllib2verfyURL{"https":"https://www.alipay.com/cooperate/gateway.do?servicenotif…

Linux驱动开发必看详解神秘内核(完全转载)

Linux驱动开发必看详解神秘内核完全转载-链接&#xff1a;http://blog.chinaunix.net/uid-21356596-id-1827434.htmlIT168 技术文档】在开始步入Linux设备驱动程序的神秘世界之前&#xff0c;让我们从驱动程序开发人员的角度看几个内核构成要素&#xff0c;熟悉一些基本的内核概…

python计算机视觉2:图像边缘检测

我是一名初学者&#xff0c;如果你发现文中有错误&#xff0c;请留言告诉我&#xff0c;谢谢 如果需要检测到图像里面的边缘&#xff0c;首先我们需要知道边缘处具有什么特征。 对于一幅灰度图像来说&#xff0c;边缘两边的灰度值肯定不相同&#xff0c;这样我们才能分辨出哪里…

oracle12c多个pdb,ProxmoxVE 之 oracle12C 多CDB和PDB

上面左边是我的个人微信&#xff0c;如需进一步沟通&#xff0c;请加微信。 右边是我的公众号“Openstack私有云”&#xff0c;如有兴趣&#xff0c;请关注。继上次在PVE环境上搭建了oracle12C RAC环境(请参考博文“ProxmoxVE 之 安装oracle12C rac集群”)并且安装使用CDB和PD…

postgresql调优

http://blog.pgaddict.com/posts/performance-since-postgresql-7-4-to-9-4-pgbench硬件和系统配置操作系统Ubuntu13.04系统位数64CPUIntel(R) Core(TM)2 Duo CPU内存4G硬盘Seagate ST2000DM001-1CH164测试工具PostgreSQL-9.1.11测试工具工具名称pgbench数据量200W&#xff08;…

操作系统--进程状态切换以及cpu调度(转)

http://www.cnblogs.com/coder2012/p/3204730.html 进程的状态转换 进程在运行中不断地改变其运行状态。通常&#xff0c;一个运行进程必须具有以下三种基本状态。 进程状态 执行态run&#xff1a;进程正在使用CPU等待态wait&#xff1a;进程正在等待I/O完成&#xff0c;不在使…

在Exchange 2010中重建Exchange安全组

问题:有时候&#xff0c;重新安装Exchange 2010会corrupt掉Exchange安全组&#xff0c;或者出现重复的组。用户在这种情况下会出现访问被拒的情况。分析:我们可以删掉这些安全组&#xff0c;然后最这些安全组进行重建&#xff1a;当你prepare ad的时候&#xff0c;由于OtherWel…

带弹出列表的EditText

最近做的一个Andriod里有一个这个要求&#xff0c;一个东西需要输入&#xff0c;但同时可以在列表直接选择。看到这个需求&#xff0c;瞬间想到了QQ的登录界面&#xff0c;那个账号输入的控件正式我所需要的。 这个账号输入框右边有一个按钮&#xff0c;点击可以显示一个下拉列…

获取win7时区所有信息

打开命令行工具&#xff1a; tzutil /l# 或者输入到文件中tzutil /l > data.txt 1 # -*- utf-8 -*-2 3 """获取win7所有时区信息&#xff0c;并写入到sql语句中4 5 Usage: python data.py -f data.txt -o data.sql6 """7 8 if __name__ &quo…

linux kill命令信号,Linux kill 命令详解

Linux kill 命令很容易让人产生误解&#xff0c;以为它仅仅就是用来杀死进程的。我们来看一下 man page 对它的解释&#xff1a;kill - send a signal to a process.从官方的解释不难看出&#xff0c;kill 是向进程发送信号的命令。当然我们可以向进程发送一个终止运行的信号&a…

VSTO学习笔记(二)Excel对象模型

原文:VSTO学习笔记&#xff08;二&#xff09;Excel对象模型上一次主要学习了VSTO的发展历史及其历代版本的新特性&#xff0c;概述了VSTO对开发人员的帮助和效率提升。从这次开始&#xff0c;将从VSTO 4.0开始&#xff0c;逐一探讨VSTO开发中方方面面&#xff0c;本人接触VSTO…

zen-coding for notepad++,前端最佳手写代码编辑器

zen-Coding是一款快速编写HTML,CSS&#xff08;或其他格式化语言&#xff09;代码的编辑器插件&#xff0c;这个插件可以用缩写方式完成大量重复的编码工作&#xff0c;是web前端从业者的利器。 zen-Coding插件支持多种编辑器&#xff0c;如UltraEdit&#xff0c;Notepad等。 温…

red hat linux 远程,Red Hat Linux 远程桌面 – 如何设置

远程访问 RHEL 计算机。运行 RHEL 7.3-8.1 的 Linux 计算机的远程桌面。从任何计算机、平板电脑或移动设备进行访问。立即免费试用&#xff01;如果您是在家中或在旅途中工作&#xff0c;则可能需要一段时间才能在办公室或在家中访问台式计算机。如果该桌面恰巧在 Linux 操作系…

通过boundingRectWithSize:options:attributes:context:计算文本尺寸

转&#xff1a;http://blog.csdn.net/jymn_chen/article/details/10949279 之前用Text Kit写Reader的时候&#xff0c;在分页时要计算一段文本的尺寸大小&#xff0c;之前使用了NSString类的sizeWithFont:constrainedToSize:lineBreakMode:方法&#xff0c;但是该方法已经被iOS…

移动后端支持平台Parse将API由Ruby迁移到Go

Charity Majors是移动后端支持平台Parse的工程师。近日&#xff0c;他撰文介绍了他们将API从Ruby迁移到Go的过程。\\2011年&#xff0c;Parse借助Ruby on Rails快速推出了第一个版本。他们用Unicorn作为HTTP服务器&#xff0c;用Capistrano部署代码&#xff0c;用RVM管理环境&a…

linux 虚拟钢琴程序,基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现,为乐器演奏(如钢琴、吉他)...

基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现&#xff0c;为乐器演奏(如钢琴、吉他)2016-08-22 0 0 0 4.0分其他1积分下载如何获取积分&#xff1f;基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现&#xff0c;为乐器演奏(如钢琴、吉他)提供稳定&#xff0c;丰富…

一个从源代码里提取中文字符串的java类

2019独角兽企业重金招聘Python工程师标准>>> 工作中需要优化代码里的中文警示语和异常信息&#xff0c;实在比较多&#xff0c;所以就写了个程序专门从代码里提取中文字符串。 java做的&#xff0c;比较简单&#xff0c;放上来备忘 package com.extractstr.app;impo…