php pcntl_fork 多进程僵尸进程的问题
来源:互联网 发布:智能开关 app 源码 编辑:程序博客网 时间:2024/05/20 03:45
因业务需要用到了pcntl_fork 处理多客户端连接处理数据的需求
但测试下来出现一个问题:
fork 之后, 若等待子进程返回, 那么程序就会阻塞, 不等待子进程返回, 则会出现僵尸进程
$obj = new service('127.0.0.1', 50000);$obj->run();class service { private $socket_id; private $socket_cid; private $pid; function __construct($host, $port) { $this->socket_id = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$this->socket_id) { $this->logs("create socket error"); return false; } if (!socket_bind($this->socket_id, $host, $port)) { $this->logs(socket_strerror(socket_last_error())); socket_close($this->socket_id); return false; } if (!socket_listen($this->socket_id)) { $this->logs(socket_strerror(socket_last_error())); socket_close($this->socket_id); return false; } } public function run() { if (!$this->socket_id) { $this->logs("create socket error"); return false; } $this->logs("Starting..."); while (true) { $this->socket_cid = socket_accept($this->socket_id); $ip = ""; socket_getpeername($this->socket_cid, $ip); $this->logs("Client IP: {$ip}"); if (!is_resource($this->socket_cid)) { $this->logs(socket_strerror(socket_last_error())); socket_close($this->socket_id); return false; } $this->pid = pcntl_fork(); if ($this->pid == -1) { $this->logs(socket_strerror(socket_last_error())); socket_close($this->socket_cid); return false; } else if ($this->pid) { $status = 0; $s = pcntl_wait($status, WNOHANG); //等待子进程中断,防止子进程成为僵尸进程, 但这样会阻塞, 意思是只能处理一个客户端连接, 多个进入排队 //$s = pcntl_waitpid(0, $status, WUNTRACED); //如果不等待, 则子进程处理完之后, 没有对其进行处理, 会成为僵尸进程 $this->logs("Status: " . $status . ", pcntl_waitpid: " . $s); } elseif ($this->pid == 0) { //child process $k = 0; while (true) { if ($data = socket_read($this->socket_cid, 1024)) { $this->logs("Read Data: {$data}"); $flag = socket_write($this->socket_cid, date('Y-m-d H:i:s') . '|已收到'); $this->logs("Write Result: {$flag}"); } sleep(1); $k++; $this->logs("Wait...\t" . date('Y-m-d H:i:s')); if ($k > 30) { break; } } socket_close($this->socket_cid); exit(1); } } socket_close($this->socket_id); } /** * 打日志 * @param string $msg * @return int */ private function logs($msg) { $logs_filename = LOGS_PATH; if (!file_exists($logs_filename)) { @mkdir($logs_filename, 0777, true); } $logs_filename .= date('j') . '.log'; $logs_data = date('[H:i:s]') . " {$msg}\n"; return file_put_contents($logs_filename, $logs_data, FILE_APPEND); } function __destruct() { if (is_resource($this->socket_id)) { socket_close($this->socket_id); } if (is_resource($this->socket_cid)) { socket_close($this->socket_cid); } }}
在网上搜了半天, 这位仁兄的解决办法是对的(http://blog.csdn.net/e421083458/article/details/22186475), 就是增加信号处理,
在socket accept之前加上 pcntl_signal(SIGCHLD, SIG_IGN); //如果父进程不关心子进程什么时候结束,子进程结束后,内核会回收。
也就是在run方法开始处 :)
public function run() { if (!$this->socket_id) { $this->logs("create socket error"); return false; } pcntl_signal(SIGCHLD, SIG_IGN); $this->logs("Starting...."); ... }
0 0
- php pcntl_fork 多进程僵尸进程的问题
- PHP多进程pcntl_fork
- pcntl_fork实现PHP多进程
- pcntl_fork实现PHP多进程
- pcntl_fork实现PHP多进程
- pcntl_fork() 子进程问题
- pcntl_fork安装以及实现PHP多进程
- PHP 多进程操作 循环pcntl_fork操作
- 僵尸进程的问题
- PHP多进程爬虫-Curl中的 SSL 和 pcntl_fork
- php多进程 防止出现僵尸进程
- PHP Linux Cli 模式下利用 pcntl_fork实现多进程处理
- linux中有关僵尸进程的问题
- linux中有关僵尸进程的问题
- 僵尸进程的原因
- Linux的僵尸进程
- 僵尸进程的避免
- 僵尸进程的避免 .
- js中鼠标滚轮事件详解
- android开发中单击事件的多种实现方法
- 数据库同步为什么不建议使用dblink方式
- unity3d热更新插件uLua学习整理
- Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)
- php pcntl_fork 多进程僵尸进程的问题
- 探索 ConcurrentHashMap 高并发性的实现机制
- android 基础知识-发展历史概述
- [Java] this与super的区别
- linux高级编程基础系列:线程间通信
- 简单的异或加密解密算法
- appium+testng报告更改
- 二叉搜索树的基本java实现
- Windows下stdlib.h与glut.h中exit()函数重复定义的解决方案