当前位置: 首页 > 图文教程 > 网络编程 > PHP > 多进程应用帮助PHP解决难题

PHP
《PHP设计模式介绍》第十三章 适配器模式
《PHP设计模式介绍》第十四章 动态记录模式
《PHP设计模式介绍》第十五章 表数据网关模式
《PHP设计模式介绍》第十六章 数据映射模式
《PHP设计模式介绍》第十七章 MVC 模式
Zend Framework 入门——快速上手
Zend Framework 入门——多国语言支持
Zend Framework 入门——错误处理
Zend Framework 入门——页面布局
详细介绍php5编程中的异常处理
PHP5 OOP编程中的代理与异常
PHP程序的常见漏洞攻击分析
PHP.MVC的模板标签系统
PHP教程:PHP编码书写规范
PHP开发大型项目的方法:OOP思想
php使用curl模拟用户登陆
php对gb编码动态转utf-8编码的几种方法评测
php设计模式介绍之章代理模式
“在phpMyAdmin使用用户口令登陆”补充
PHP入门速成

多进程应用帮助PHP解决难题


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 77 ::
收藏到网摘: n/a

PHP在很多时候不适合做常驻的SHELl进程, 他没有专门的gc例程, 也没有有效的内存管理途径. 所以如果用PHP做常驻SHELL, 你会经常被内存耗尽导致abort而unhappy.
而且, 如果输入数据非法, 而脚本没有检测, 导致abort, 也会让你很不开心.

那? 怎么办呢?

呵呵, 别着急, 多进程来帮您!

那,这是为什么呢?

优点:

1. 使用多进程, 子进程结束以后, 内核会负责回收资源

2. 使用多进程,子进程异常退出不会导致整个进程Thread退出. 父进程还有机会重建流程.

3. 一个常驻主进程, 只负责任务分发, 逻辑更清楚.


Then, 怎么做呢?

接下来, 我们使用PHP提供的POSIX和Pcntl系列函数, 来实现一个PHP命令解析器, 主进程负责接受用户输入, 然后fork子进程执行, 并负责回显子进程的结束状态.
代码如下, 我加了注释, 如果有不懂的地方, 可以翻阅手册相关函数, 或者回复留言.

#!/bin/env php
<?php
/** A example denoted muti-process application in php
* @filename fork.php
* @touch date Wed 10 Jun 2009 10:25:51 PM CST
* @author Laruence<[email protected]>
* @license http://www.zend.com/license/3_0.txt   PHP License 3.0
* @version 1.0.0
*/
/** 确保这个函数只能运行在SHELL中 */
if
(substr(php_sapi_name(), 0, 3) !== 'cli')
{
die("This Programe can only be run in CLI mode");
}
/**  关闭最大执行事件限制, 在CLI模式下, 这个语句其实不必要 */
set_time_limit(0);

$pid  = posix_getpid(); //取得主进程ID
$user = posix_getlogin(); //取得用户名
echo
<<<EOD
USAGE: [command | expression]
input php code to execute by fork a new process
input quit to exit

        Shell Executor version 1.0.0 by laruence
EOD;
while
(true)
{
$prompt = "\n{$user}$ ";
        $input  = readline($prompt);

        readline_add_history($input);
        if
($input == 'quit')
{
break;
        }
process_execute($input . ';');
}
exit(0);

function
process_execute($input)
{
$pid = pcntl_fork(); //创建子进程
if
($pid == 0)
{//子进程
$pid = posix_getpid();
                echo
"* Process {$pid} was created, and Executed:\n\n";
                eval($input); //解析命令
exit;
        }
else
{//主进程
$pid = pcntl_wait($status, WUNTRACED); //取得子进程结束状态
if
(pcntl_wifexited($status))
{
echo
"\n\n* Sub process: {$return['pid']} exited with {$status}";
                }
}
}