azielinski / simple-process

PHP pcntl fork 函数的简单封装

dev-master 2015-05-09 13:22 UTC

This package is not auto-updated.

Last update: 2024-09-23 14:49:34 UTC


README

这个小型库使得使用 pcntl 扩展变得简单;强烈建议您也看看 PThreads 库(http://pthreads.org),它比这个微小的封装更强大;我之所以编写它,仅仅是因为在我的使用场景中,使用 PThreads 不是一个选择。

安装

需求

PHP >= 5.3
pcntl extension installed

Composer

只需将以下行添加到您的 "require": 部分

"azielinski/simple-process": "dev-master"

您不使用 composer 吗?

那么只需克隆仓库 :) 您还需要手动 include 所有四个文件。

基本使用

基本使用看起来像这样

declare(ticks=1); // This part is critical, be sure to include it
$manager = new SimpleProcess\ProcessManager();
$manager->fork(new SimpleProcess\Process(function() { sleep(5); }, "My super cool process"));
    
do
{
    foreach($manager->getChildren() as $process)
    {
        $iid = $process->getInternalId();
        if($process->isAlive())
        {
            echo sprintf('Process %s is running', $iid);
        } else if($process->isFinished()) {
            echo sprintf('Process %s is finished', $iid);
        }
        echo "\n";
    }
    sleep(1);
} while($manager->countAliveChildren());

就这样!子进程将只执行提供的可调用函数,因此无需担心“我是否在这个行的正确进程中?”;父进程在调用 ->fork() 后继续正常执行;ProcessManager 类还负责回收子进程,因此您可以专注于应用程序的逻辑,而不是 pcntl_* 函数使用的阴暗角落。

父进程与子进程之间的通信

ProcessManager 可能会为每个子进程分配一些共享内存 - 然后您可以从父进程访问它

declare(ticks=1); // This part is critical, be sure to include it
$manager = new SimpleProcess\ProcessManager();
$manager->allocateSHMPerChildren(1000); // allocate 1000 bytes for each forked process
for($i=0;$i<4;$i++)
{
    $manager->fork(new SimpleProcess\Process(function(SimpleProcess\Process $currentProcess) {
        $currentProcess->getShmSegment()->save('status', 'Processing data...');
        sleep(5);
        $currentProcess->getShmSegment()->save('status', 'Connecting to the satellite...');
        sleep(5);
    }, $i));
}
$manager->cleanupOnShutdown(); // Register shutdown function that will release allocated shared memory;
                               // It is important to call this after all fork() calls, as we don't want
                               // to release it when child process exits

do
{
    foreach($manager->getChildren() as $process)
    {
        $iid = $process->getInternalId();
        if($process->isAlive())
        {
            echo sprintf('Process %s is running with status "%s"', $iid, $process->getShmSegment()->fetch('status'));
        } else if($process->isFinished()) {
            echo sprintf('Process %s finished execution', $iid);
        }
        echo "\n";
    }
    sleep(1);
} while($manager->countAliveChildren());

$manager->cleanup(); // You can also call cleanup() manually if you want to

其他事项

此库还提供了 Semaphore 类,以防您需要在代码中某处使用信号量;使用方法如下

$s = SimpleProcess\Semaphore::create('critical_section');
$s->acquire();
$s->release();