当前位置: 首页 > 编程日记 > 正文

守护进程中创建的对象php,在PHP中生成守护进程(Daemon Process)

前两天看到一篇文章《如何使用PHP编写daemon process》,其中对核心代码却没有细说,我又查了一些资料,还看了一本《理解Unix进程》,才搞明白生成守护进程的时候发生了什么。

这段代码是这个样子的:

function run()

{

//第一次fork,父进程与子进程在此分开

if(($pid1 = pcntl_fork()) === 0)

{

//子进程在此成为会话组leader

posix_setsid();

//第二次fork,子进程与孙子进程在此分开

if(($pid2 = pcntl_fork()) === 0)

{

//孙子进程成为守护进程,开始处理任务

handle_http_request('www.codinglabs.org', 9999);

}

else

{

//子进程退出,将孙子进程交由init托管

exit;

}

}

else

{

//父进程在此等待子进程的退出信号

pcntl_wait($status);

}

}

如果不理解这段代码的话,可能需要了解一些Unix系统进程的知识。

0. 系统调用

Unix系统由用户空间和内核组成,系统调用允许用户空间的程序通过内核与计算机硬件交互。不同的语言可以通过不同的函数使用系统调用,例如系统调用fork在C中的函数是fork(),在PHP中的函数是pcntl_fork(). PCNTL是Process Control的缩写,PHP中与进程有关的函数都以此开头。

1. 子进程

系统中的每个进程都有对应的父进程,进程的ppid标识符即为其父进程的pid。当子进程执行完毕之后,父进程应该通过wait请求这些信息,否则内核会一直保留子进程的状态信息。如果父进程没有调用wait来等待它,子进程就会变成僵尸进程。

如果父进程先于子进程结束,子进程通常并不会受影响,而会一直执行下去。父进程结束时系统会扫描其子进程,并将其ppid置为1,成为init进程的子进程。

2. fork

系统调用fork可以使进程衍生一个子进程。两个进程除了pid与ppid之外一模一样。PHP中可以通过pcntl_fork()实现fork,执行完该函数之后,代码会在父子两个进程中继续执行下去,pcntl_fork()在子进程中的返回值为0,在父进程中的返回值为子进程的pid。因此pcntl_fork()经常被放在if条件里,以实现父子进程执行不同的代码,例如:

if(($pid1 = pcntl_fork()) === 0)

{

//子进程执行此处的代码

}

else

{

//父进程执行此处的代码

}

3. 进程组

每个进程都属于某个组,进程组是一个相关进程的集合,通常是父进程与其子进程。每个进程组都有一个整数id,可以通过posix_getpgrp()函数获得,通常进程组的id和进程组leader的pid相同。当终端收到终止信号(Ctrl-C)时,会转发给进程组中的所有进程。因此,如果你在终端执行一个PHP脚本,并在脚本中fork了子进程。当在终端中按Ctrl-C终止脚本执行时,子进程会同时被中止。

4. 会话组

会话组是进程组的集合,当在shell中执行命令:git log | grep shipped | less时,每个命令都有一个进程组,三个进程组属于同一个会话组。当终端收到Ctrl-C时,发送给会话leader的信号会被转发给该会话组的每个进程组,然后再被转发到进程组中的所有进程。

5. setsid

setsid系统调用会使衍生进程成为一个新会话组leader(同时也是新进程组leader),并返回新建的会话组id。在PHP中对应的函数是posix_setsid();

6. 为何要fork两次。

这个问题就是这段代码中最难解释的部分了,有一些人认为只fork一次就够用了,剩下的观点分为两种,一种是两次fork是为了杜绝守护进程控制终端的可能,另一种认为两次fork是为了避免产生僵尸进程。

6.1. 防止守护进程控制终端

如果要生成一个守护进程,我们应该确保它不会控制终端,完全在后台运行。而只有会话组leader才能控制终端,因此就要确保守护进程不是会话组leader,这就是第二次fork的作用。

第一次fork并setsid使进程脱离当前终端,第二次fork确保进程永远不会控制终端。

6.2. 避免守护进程成为僵尸进程

网上另有一种说法是,父进程的存在并非只为生成守护进程。如果只fork一次,且父进程不退出,那么守护进程终止之后就会成为僵尸进程。因此要生成一个子进程来fork出守护进程,fork出守护进程之后子进程就exit,以便将守护进程交由init进程托管。我不是很倾向于这种说法,因为很多fork两次的代码中都不存在「父进程生成守护进程后,还有自己的事要做,它的人生意义并不只是为了生成守护进程」这种事。

现在再看回头看一下那段代码,应该很容易理解了。

相关文章:

log4j个人使用整理

Log4j介绍: 略过。 配置: Eclipse项目中添加log4j.jar到lib下。 在bin目录下新建log4j.properties,编辑好log4j配置文件。 样例分析: 1 log4j.rootLoggerWARN, stdout, file2 log4j.appender.stdoutorg.apache.log4j.ConsoleAppen…

完全理解 Python 迭代对象、迭代器、生成器(转)

完全理解 Python 迭代对象、迭代器、生成器 本文源自RQ作者的一篇博文,原文是Iterables vs. Iterators vs. Generators nvie.com,俺写的这篇文章是按照自己的理解做的参考翻译,算不上是原文的中译版本,推荐阅读原文,谢…

Rocksdb 与 TitanDb 原理分析 及 性能对比测试

文章目录前言Rocksdb的compaction机制compaction作用compaction分类level style compaction(rocksdb 默认进行的compaction策略)level 的文件存储结构compaction过程compaction中的level target sizeuniversal style compactionfifo style compactionTit…

经典SQL练习题

题目地址:http://blog.csdn.net/qaz13177_58_/article/details/5575711 1、 查询Student表中的所有记录的Sname、Ssex和Class列。select sname,ssex,class from STUDENT2、 查询教师所有的单位即不重复的Depart列。select depart from TEACHER group by departselec…

php url模式在哪修改,php如何修改url

php如何修改url2020-07-03 12:15:40php修改url的方法:1、通过配置文件修改URL规则;2、设置URL伪静态,即限制伪静态的后缀;3、在配置文件中开启路由支持,并配置路由;4、将URL进行重写即可。PHP对URL设置一、…

国外十大最流行PHP框架排名

以下为十个目前最流行的基于MVC设计模式的PHP框架。1. YiiYii是一个基于组件的高性能的PHP的框架,用于开发大规模Web应用。Yii采用严格的OOP编写,并有着完善的库引用以及全面的教程。从MVC,DAO/ActiveRecord,widgets,c…

python_web框架

一、web框架 web框架: 自己完成socket的web框架:如,Tornado等由WSGI完成socket的web框架:如,Django、flash等两种实现过程: 第二种WSGI方式的,由于自带socket所以可直接写后端代码。 python标准…

g-gdb 调试多线程

代码调试工具gdb是一个能够让我们在工作中高效排查代码异常根源的利器。 在此将gdb针对多线程的调试方式做一个笔记,也方便后续回顾以及分享大家。 本文采用的是一个简单的多线程代码示例,同时调试是在mac上进行的 mac安装gdb brew install gdb即可 基…

php数据库html文本,关于php,mysql,html的数字分页和文本_php

请勿盗版,转载请加上出处http://blog.csdn.net/yanlintao1请勿盗版,转载请加上出处http://blog.csdn.net/yanlintao1首先进行样式展示希望对大家有所帮助,也希望大家给出意见和建议:第一种:数字分页第二种:…

WinDbg加载不同版本CLR

WinDbg调试.net2.0和.net4.0程序有所不同,因为.net4.0使用新版本的CLR。例如: mscoree.dll 变为 mscoree.dll 和 mscoreei.dll, mscorwks.dll 变为 clr.dll, mscorjit.dll 变为 clrjit.dll。 因此,在.net2.0加载mscorj…

交换机***工具——Yersinia

Yersinia是国外一款专门针对交换机执行第二层***的***工具。目前的版本是0.7.1。目前支持的操作系统及版本号如表1所示。表1 Yerdinia支持的操作系统操作系统名称版本号OpenBSD3.4 (pcap库版本至少0.7.2以上)Linux2.4.x和2.6.xSolaris5.8 64bits SPARCMac OSX10.4 Tiger (Intel…

Rocksdb 写流程,读流程,WAL文件,MANIFEST文件,ColumnFamily,Memtable,SST文件原理详解

文章目录前言Rocksdb写流程图WAL 原理分析概述文件格式查看WAL的工具创建WAL清理WALMANIFEST原理分析概述查看MANIFEST的工具创建 及 清除 MANIFEST文件内容CcolumnFamily 详解概述API介绍核心数据结构创建以及删除MEMTABLE 实现概述实现Rocksdb写入逻辑概述实现总结关于写的一…

react 入门

首先安装node.js环境 下载地址 https://nodejs.org/en/download/检查安装版本 进入命令行npm -v~~3. 安装react命令环境 npm install - g react-native-cli ~~~ 初始化项目 FirstAppreact-native init FirstApp 转载于:https://www.cnblogs.com/liu-ya/p/10511537.html

将字符串打乱输出

将字符串打乱输出 Dim i,mm,Str,StrPosition,NewStrStr  "1234567890"For i1 To Len(Str)    StrPosition  GetRandomMath(1,Len(Replace(Str,mm,"")))    Str  Replace(Str,mm,"")    mm  Mid(str,StrPosition,1)   …

php帝国系统调出图片内空,帝国CMS图集字段的大图,小图,说明的调用方法

本文实例讲述了帝国CMS图集字段的大图,小图,说明的调用方法。分享给大家供大家参考。具体方法如下:复制代码代码如下:$arr array();$arr $navinfor[morepic];$newarr explode(egetzy(rn),$arr);$count count(explode(egetzy(rn),$navinfor[morepic]));//图集的图…

static和global的区别

1.global在整个页面起作用。2.static只在function和class内起作用。global和$GLOBALS使用基本相同,但在实际开发中大不相同。global在函数产生一个指向函数外部变量的别名变量,而不是真正的函数外部变量,一但改变了别名变量的指向地址&#x…

vue 之 nextTick 与$nextTick

VUE中Vue.nextTick()和this.$nextTick()怎么使用? 官方文档是这样解释的: 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。 虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考&#xff…

Linux创建线程时 内存分配的那些事

文章目录问题描述问题分析针对问题1 的猜测:针对问题2 的猜测:原理追踪总结问题描述 事情开始于一段内存问题,通过gperf工具抓取进程运行过程中的内存占用情况。 分析结果时发现一个有趣的事情,top看到的实际物理内存只有几兆,但是pprof统计…

mysql plsql循环语句吗,Oracle PLSQL 在游标中用while循环实例程序

Oracle PLSQL 在游标中用while循环实例程序Oracle PLSQL 在游标中用while循环实例程序Oracle PLSQL 在游标中用while循环实例程序declarecursor emp_cur is select * from emp;v_emp emp%rowType;beginopen emp_cur;while emp_cur%notfound --while肯定要跟loop一起用的 且是控…

【原创】Linux环境下的图形系统和AMD R600显卡编程(11)——R600指令集

1 低级着色语言tgsi OpenGL程序使用GLSL语言对可编程图形处理器进行编程,GLSL语言(以下高级着色语言就是指GLSL)是语法类似C的高级语言,在GLSL规范中,GLSL语言被先翻译成教低级的类汇编语言,然后被翻译成硬…

VBScript中InStr函数的用法

InStr([start, ]str1, str2[, compare]) [用途]:返回str2在str1中的位置。匹配成功时,返回值最小值为1,未匹配到时返回0。 [参数说明]: start:在str1中开始匹配的位置,1表示从头开始,不能为0或更小值。 可选…

洛谷P3122 [USACO15FEB]圈住牛Fencing the Herd(计算几何+CDQ分治)

题面 传送门 题解 题目转化一下就是所有点都在直线\(AxBy-C0\)的同一侧,也就可以看做所有点代入\(AxBy-C\)之后的值符号相同,我们只要维护每一个点代入直线之后的最大值和最小值,看看每条直线的最大最小值符号是否相同就好了 以最大值为例&am…

skiplist跳表的 实现

文章目录前言跳表结构时间复杂度空间复杂度高效的动态插入和删除跳表索引的动态更新总结详细实现前言 rocksdb 的memtable中默认使用跳表数据结构对有序数据进行的管理,为什么呢? 同时redis 也用跳表作为管理自己有序集合的数据结构,为什么…

php的反射作用是什么意思,php反射的作用是什么

反射是在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大&#…

《BI项目笔记》用Excel2013连接和浏览OLAP多维数据集

《BI项目笔记》用Excel2013连接和浏览OLAP多维数据集 原文:《BI项目笔记》用Excel2013连接和浏览OLAP多维数据集用Excel2013连接和浏览OLAP多维数据集 posted on 2014-12-02 08:58 NET未来之路 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/lonelyxmas/p/413…

mac 拷贝文件时报错 8060 解决方案

解决如下: 即某文件夹下出现多重子目录,级数很多,删除多余的子文件夹即可。 至于如何产生的,有人说是xcode升级导致,不过没有见证 。我的不属于这类情况的。 (参见:http://macosx.com/forums/ma…

C#连接数据库

VScode 配置C#环境 https://blog.csdn.net/qq_40346899/article/details/80955788VScode 配置C#开发环境 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;using System.Data; using System.Data.SqlCli…

C++ 中emplace_back和push_back差异

前言 最近看rocskdb源码,发现了大量的设计模式和C高级特性,特此补充一下,巩固基础。 问题描述 其中关于动态数组的元素添加,代码中基本将push_back抛弃掉了,全部替换为emplace_back进行元素的添加。 看了一下官网描…

[51单片机学习笔记ONE]-----LED灯的多种使用方法

一.交替闪烁8个LED灯,时间间隔为1s 1 /******************************************************2 实验名称: 交替闪烁8个LED灯,时间间隔1s3 实验时间: 2014年12月2日4 ******************************************************/…

php 伪协议 lfi,php://伪协议(I/O)总能给你惊喜——Bugku CTF-welcome to bugkuctf

今天一大早BugkuCTF 的welcome to bugkuctf 就给了我一发暴击:完全不会啊。。。光看源码就发现不知道怎么处理了,于是转向writeup求助。结果发现这是一道非常有营养的题目,赶紧记录一下。题目链接:http://123.206.87.240:8006/tes…