资讯专栏INFORMATION COLUMN

PHP多进程初探 --- 利用多进程开发点儿东西吧

huaixiaoz / 3201人阅读

摘要:主进程退出子进程继续执行给进程重新起个名字加入我们出个子进程就可以搞定这些任务,那么出个子进程,同时父进程要负责这个子进程的状态等。

[原文地址:https://blog.ti-node.com/blog...]

干巴巴地叨逼叨了这么久,时候表演真正的技术了!

做个高端点儿的玩意吧,加入我们要做一个任务系统,这个系统可以在后台帮我们完成一大波(注意是一大波)数据的处理,那么我们自然想到,多开几个进程分开处理这些数据,同时我们不能执行了php task.php后终端挂起,万一一不小心关闭了终端都会导致任务失败,所以我们还要实现程序的daemon化。好啦,开始了!

首先,我们第一步就得将程序daemon化了!

    // 设置umask为0,这样,当前进程创建的文件权限则为777
    umask( 0 );
    $pid = pcntl_fork();
    if( $pid < 0 ){
      exit("fork error.");
    } else if( $pid > 0 ) {
      // 主进程退出
      exit();
    }
    // 子进程继续执行
    
    // 最关键的一步来了,执行setsid函数!
    if( !posix_setsid() ){
      exit("setsid error.");
    }
    
    // 理论上一次fork就可以了
    // 但是,二次fork,这里的历史渊源是这样的:在基于system V的系统中,通过再次fork,父进程退出,子进程继续
    // 保证形成的daemon进程绝对不会成为会话首进程,不会拥有控制终端。
    $pid = pcntl_fork();
    if( $pid  < 0 ){
      exit("fork error");
    } else if( $pid > 0 ) {
      // 主进程退出
      exit;
    }
    // 子进程继续执行
    // 给进程重新起个名字
    cli_set_process_title("php master process");
    

加入我们fork出5个子进程就可以搞定这些任务,那么fork出5个子进程,同时父进程要负责这5个子进程的状态等。

// 由于*NIX好像并没有(如果有,请告知)可以获取父进程fork出所有的子进程的ID们的功能,所以这个需要我们自己来保存
$child_pid = [];

// 父进程安装SIGCHLD信号处理器并分发
pcntl_signal( SIGCHLD, function(){
  // 这里注意要使用global将child_pid全局化,不然读到去数组将为空,具体原因可以自己思考下
  global $child_pid;
  // 如果子进程的数量大于0,也就说如果还有子进程存活未 退出,那么执行回收
  $child_pid_num = count( $child_pid );
  if( $child_pid_num > 0 ){
    // 循环子进程数组
    foreach( $child_pid as $pid_key => $pid_item ){
      $wait_result = pcntl_waitpid( $pid_item, $status, WNOHANG );
      // 如果子进程被成功回收了,那么一定要将其进程ID从child_pid中移除掉
      if( $wait_result == $pid_item || -1 == $wait_result ){
        unset( $child_pid[ $pid_key ] );
      }
    }
  }
} );

// fork出5个子进程出来,并给每个子进程重命名
for( $i = 1; $i <= 5; $i++ ){
  $_pid = pcntl_fork();
  if( $_pid < 0 ){
    exit();
  } else if( 0 == $_pid ) {
    // 重命名子进程
    cli_set_process_title("php worker process");
    
    // 啦啦啦啦啦啦啦啦啦啦,请在此处编写你的业务代码
    // do something ...
    // 啦啦啦啦啦啦啦啦啦啦,请在此处编写你的业务代码
    
    // 子进程退出执行,一定要exit,不然就不会fork出5个而是多于5个任务进程了
    exit();
    
  } else if( $_pid > 0 ) {
    // 将fork出的任务进程的进程ID保存到数组中
    $child_pid[] = $_pid;
  }
}

// 主进程继续循环不断派遣信号
while( true ){
  pcntl_signal_dispatch();
  // 每派遣一次休眠一秒钟
  sleep( 1 );
}

[原文地址:https://blog.ti-node.com/blog...]

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

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

相关文章

  • PHP进程初探 --- 开篇

    摘要:所以我们只说的多进程,至于多线程就暂时放到一边儿。出来新进程则成为子进程,原进程则成为父进程,子进程拥有父进程的副本。在父进程中返回子进程的进程,在子进程内部本身返回数字。 [原文地址:https://blog.ti-node.com/blog...] 实际上PHP是有多线程的,只是很多人不常用。使用PHP的多线程首先需要下载安装一个线程安全版本(ZTS版本)的PHP,然后再安装pec...

    wh469012917 评论0 收藏0
  • PHP进程初探 --- 再次谈daemon进程

    摘要:因为子进程一定不会是组长进程,所以子进程可以调用。主进程退出子进程继续执行啦啦啦,啦啦啦,啦啦啦,已经变成啦,开心一般服务器软件都有写配置项,比如以模式运行还是以模式运行。 [原文地址:https://blog.ti-node.com/blog...] 其实前面是谈过一次daemon进程的,但是并涉及过多原理,但是并不影响使用。今天打算说说关于daemon进程更多的二三事,本质上说,如...

    fox_soyoung 评论0 收藏0
  • PHP socket初探 --- 一些零碎细节的拾漏补缺

    摘要:原文前面可以说是弄了一系列的和多进程的一大坨内容,知识浅显代码粗暴风格简陋,总的说来,还是差了一些细节。今天,就一些漏掉的细节补充一下。最后,我补充一句是同步的,而不是异步。 原文:https://t.ti-node.com/thread/... 前面可以说是弄了一系列的php socket和多进程的一大坨内容,知识浅显、代码粗暴、风格简陋,总的说来,还是差了一些细节。今天,就一些漏...

    chengjianhua 评论0 收藏0
  • PHP socket初探 --- select系统调用

    摘要:原文地址在初探先从一个简单的服务器开始中依次讲解了三个逐渐进步的服务器只能服务于一个客户端的服务器利用可以服务于多个客户端的额服务器利用预派生进程服务于多个客户端的服务器最后一种服务器的进程模型基本上的大概原理其实跟我们常用的是非常 [原文地址:https://blog.ti-node.com/blog...] 在<PHP socket初探 --- 先从一个简单的socket服务器开始...

    springDevBird 评论0 收藏0

发表评论

0条评论

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