[原文地址:https://blog.ti-node.com/blog...]php
干巴巴地叨逼叨了这么久,时候表演真正的技术了!node
作个高端点儿的玩意吧,加入咱们要作一个任务系统,这个系统能够在后台帮咱们完成一大波(注意是一大波)数据的处理,那么咱们天然想到,多开几个进程分开处理这些数据,同时咱们不能执行了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个子进程的状态等。spa
// 因为*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...]code