资讯专栏INFORMATION COLUMN

php多进程通信,有名管道(pcntl学习 五)

newtrek / 1441人阅读

摘要:对于多进程间的通信,研究了一天的管道,封装了一个管道类,以及处理多进程的类。管道的理论,后期再补上,先上代码。

对于多进程间的通信,研究了一天的管道,封装了一个管道类,以及处理多进程的类。管道的理论,后期再补上,先上代码。

path = $path;
                return $this;
            }
        }
        if (posix_mkfifo($path,$mode)) {
            $this->path = $path;
            return $this;
        } else {
            $this->throwException("create pipe failed");
        }
    }
    /**
     * 抛异常方法
     */
    public function throwException($msg = "failed")
    {
        throw new Exception($msg);
    }
    /**
     * 设置阻塞方式
     * 
     * @param   bool   $block false为非阻塞,true为阻塞
     */
    public function setBlock($block = false)
    {
        $this->block = $block;
    }
    /**
     * 指定pipe文件路径
     */
    public function setPath($path)
    {
        if (!file_exists($path)) {
            $msg = $path." pipe  does not exists";
            $this->throwException($msg);
        }
        $this->path = $path;
    }
    /**
     * 获取pipe文件路径
     */
    public function getPath()
    {
        return $this->path;
    }
    /**
     * 打开一个管道
     *
     * @param   string   $mode  打开类型
     */
    public function pipeOpen($mode = "r")
    {
        $handler = fopen($this->path, $mode);
        if (!is_resource($handler)) {
            $msg = "open pipe ".$this->path." falied";
            $this->throwException($msg);
        }
        // 设置阻塞类型
        stream_set_blocking($handler, $this->block);
        $this->handler = $handler;
        return $this;
    }
    /**
     * 已读的方式打开管道
     *
     * @return resource
     */
    public function readOpen()
    {
        return $this->pipeOpen("r");
    }
    /**
     * 已写的方式打开管道
     *
     * @return resource
     */
    public function writeOpen()
    {
        return $this->pipeOpen("w");
    }
    /**
     * 读取一行,或给定的长度
     */
    public function readOne($byte = 1024)
    {
        $data = fread($this->handler,$byte);
        return $data;
    }
    /**
     * 读取所有的内容
     */
    public function readAll()
    {
        $hd = $this->handler;
        $data = "";
        while (!feof($hd)) {
            $data .= fread($hd,1024);
        }
        return $data;
    }
    /**
     * 写入数据
     */
    public function write($data)
    {
        $hd = $this->handler;
        try {
            fwrite($hd,$data);
        } catch(Exception $e) {
            $this->throwException($e->getMessage());
        }
        return $this;
    }
    /**
     * 关闭管道
     */
    public function close()
    {
        return fclose($this->handler);
    }
    /**
     * 删除管道
     */
    public function remove()
    {
        return unlink($this->path);
    }
    
}

多进程处理类,利用管道保存各个进程的返回结果,主进程处理最后的结果

process  = $process;
    }
    /**
     * 设置子进程
     */
    public function setProcess($process)
    {
        $this->process = $process;
    }
    /**
     * fork 子进程
     */
    public function forkProcess()
    {
        $process  = $this->process;
        foreach($process as $k => $item) {
            $pid = pcntl_fork();
            if ($pid ==  0) {
                $pipe = new fifoPipeClass();
                $id = getmypid();
                $pipe->writeOpen();
                $pipe->write($k." pid:".$id.PHP_EOL);
                $pipe->close();
                exit(0);
            } else if ($pid > 0) {
                $this->child[] = $pid;
            }
        }
        return $this;
    }
    /**
     * 等待子进程结束
     */
    public function waiteProcess()
    {
        $child = $this->child;
        $pipe  = new fifoPipeClass();
        $pipe->readOpen();
        echo "get all begin".PHP_EOL;
        while(count($child)) {
            foreach($child as $k => $pid){
                $res = pcntl_waitpid($pid,$status,WNOHANG);
                if ( -1 == $res || $res > 0 ) {
                    unset($child[$k]);
                }
            }
            $data = $pipe->readOne();
            if ($data) {
                $this->result[] = $data;
            }
        }
        $pipe->close();
        echo "get all end".PHP_EOL;
        $pipe->remove();
        return $this;
    }
    /**
     * 获取返回结果
     */
    public function getResult()
    {
        return $this->result;
    }
}
$obj = new pipeMultiProcess();
$obj->setProcess(["name"=>1,"age"=>2,"sex"=>3]);
$res = $obj->forkProcess()->waiteProcess()->getResult();
print_r($res);

运行结果如下:

Array
(
    [0] => age pid:7436

    [1] => sex pid:7437
name pid:7435

)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22794.html

相关文章

  • PHP回顾之进程编程

    摘要:多进程中与多进程相关的两个重要拓展是和。函数执行期间,主进程除了等待无法处理其他任务,所以一般不认为这是多进程编程。回收子进程有两种方式,一种是主进程调用函数等待子进程结束另外一种是处理信号。 转载请注明文章出处: https://tlanyan.me/php-review... PHP回顾系列目录 PHP基础 web请求 cookie web响应 session 数据库操作 加解...

    lifesimple 评论0 收藏0
  • PHP进程系列笔记(

    摘要:消息队列更常见的用途是主进程分配任务,子进程消费执行。子进程前面加了个,这是为了防止父进程还未往消息队列中加入内容直接退出。 前面几节都是讲解pcntl扩展实现的多进程程序。本节给大家介绍swoole扩展的swoole_process模块。 swoole多进程 swoole_process 是swoole提供的进程管理模块,用来替代PHP的pcntl扩展。 首先,确保安装的swoole...

    qianfeng 评论0 收藏0
  • 从0到1优雅的实现PHP进程管理

    摘要:目的综上所述,我的目标就是实现基于模式实现的多进程管理工具。备注下文中,父进程统称为子进程统称为。最后我们通过下图来简单的总结和描述这个多进程实现的过程控制上面实现了多进程和多进程的常驻内存,那如何去管理呢答案多进程通信。 _ | | _ __ __ _ _ __...

    lakeside 评论0 收藏0
  • PHP 命令行方式实现异步进程模式的任务处理

    摘要:定义任务处理方法。读取来自命令行的参数,开始执行任务。该函数有两个参数和,是引用类型,用来存储子进程的状态,有两个可选常量,分别表示不等待子进程结束立即返回和等待子进程结束。 用PHP来实现异步任务一直是个难题,现有的解决方案中:PHP知名的异步框架有 swoole 和 Workerman,但都是无法在 web 环境中直接使用的,即便强行搭建 web 环境,异步调用也是使用多进程模式实...

    Invoker 评论0 收藏0
  • PHP 进程的实现与管理

    摘要:运行模式实现进程前,需了解常见的的运行模式通用网关接口模式模式命令行模式模块模式作为服务器模块而进程则是使用命令行模式运行的基本实现中提供了一个扩展,可以利用操作系统的调用来实现多进程。 应用场景 一些耗时任务: 大数据表分表后的统计信息功能 分批发送短信或邮件功能 其他可分目标的任务功能(很多种) 所以我们就需要一个常驻内存的任务管理工具,为了保证实时性,一方面我们让它一直执行任...

    MockingBird 评论0 收藏0

发表评论

0条评论

newtrek

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<