PHP有一组进程控制函数(编译时需要–enable-pcntl与posix扩展),使得php能实现跟c一样的创建子进程、使用exec函数执行程序、处理信号等功能。
<"pcntl_fork")) { die("pcntl extention is must !"); } //总进程的数量 $totals = 3; // 执行的脚本数量 $cmdArr = array(); // 执行的脚本数量的数组 for ($i = 0; $i < $totals; $i++) { $cmdArr[] = array("path" => __DIR__ . "/run.php", 'pid' =>$i ,'total' =>$totals); } /* 展开:$cmdArr Array ( [0] => Array ( [path] => /var/www/html/company/pcntl/run.php [pid] => 0 [total] => 3 ) [1] => Array ( [path] => /var/www/html/company/pcntl/run.php [pid] => 1 [total] => 3 ) [2] => Array ( [path] => /var/www/html/company/pcntl/run.php [pid] => 2 [total] => 3 ) ) */ pcntl_signal(SIGCHLD, SIG_IGN); //如果父进程不关心子进程什么时候结束,子进程结束后,内核会回收。 foreach ($cmdArr as $cmd) { $pid = pcntl_fork(); //创建子进程 //父进程和子进程都会执行下面代码 if ($pid == -1) { //错误处理:创建子进程失败时返回-1. die('could not fork'); } else if ($pid) { //父进程会得到子进程号,所以这里是父进程执行的逻辑 //如果不需要阻塞进程,而又想得到子进程的退出状态,则可以注释掉pcntl_wait($status)语句,或写成: pcntl_wait($status,WNOHANG); //等待子进程中断,防止子进程成为僵尸进程。 } else { //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。 $path = $cmd["path"]; $pid = $cmd['pid'] ; $total = $cmd['total'] ; echo exec("/usr/bin/php {$path} {$pid} {$total}")."\n"; exit(0) ; } } "htmlcode"><"Caught SIGALRM\n"; pcntl_alarm(5); } pcntl_signal(SIGALRM, "signal_handler", true); pcntl_alarm(5); for(;;) { } "htmlcode"><"htmlcode"><"htmlcode"><"parent process,pid {$id}, child pid {$pid}\n"; }else{ $id = getmypid(); echo "child process,pid {$id}\n"; sleep(2); } "htmlcode"><"Method '__fork' not found!"); } if(is_array($arg)){ $i=0; foreach($arg as $key=>$val){ $spawns[$i]=$key; $i++; $this->spawn($obj,$key,$val); } $spawns['total']=$i; }elseif($spawns=intval($arg)){ for($i = 0; $i < $spawns; $i++){ $this->spawn($obj,$i); } }else{ exit('Bad argument!'); } if($i>1000) exit('Too many spawns!'); return $this->request($spawns); } /** * Signfork主进程控制方法 * 1、$tmpfile 判断子进程文件是否存在,存在则子进程执行完毕,并读取内容 * 2、$data收集子进程运行结果及数据,并用于最终返回 * 3、删除子进程文件 * 4、轮询一次0.03秒,直到所有子进程执行完毕,清理子进程资源 * @param string|array $arg 用于对应每个子进程的ID * @return array 返回 array([子进程序列]=>[子进程执行结果]); */ private function request($spawns){ $data=array(); $i=is_array($spawns)"htmlcode"><"pcntl_fork")){ //生成子进程 $pid = pcntl_fork(); if($pid == -1){ die('could not fork'); }else{ if($pid){ $status = 0; //阻塞父进程,直到子进程结束,不适合需要长时间运行的脚本,可使用pcntl_wait($status, 0)实现非阻塞式 pcntl_wait($status); // parent proc code exit; }else{ // child proc code //结束当前子进程,以防止生成僵尸进程 if(function_exists("posix_kill")){ posix_kill(getmypid(), SIGTERM); }else{ system('kill -9'. getmypid()); } exit; } } }else{ // 不支持多进程处理时的代码在这里 } //..... "htmlcode"><"htmlcode">#include "apue.h" #include <sys/wait.h> int main(void){ pid_t pid; if ((pid = fork()) < 0){ err_sys("fork error"); } else if (pid == 0){ /**//* first child */ if ((pid = fork()) < 0){ err_sys("fork error"); }elseif(pid > 0){ exit(0); /**//* parent from second fork == first child */ } /** * We're the second child; our parent becomes init as soon * as our real parent calls exit() in the statement above. * Here's where we'd continue executing, knowing that when * we're done, init will reap our status. */ sleep(2); printf("second child, parent pid = %d ", getppid()); exit(0); } if (waitpid(pid, NULL, 0) != pid) /**//* wait for first child */ err_sys("waitpid error"); /** * We're the parent (the original process); we continue executing, * knowing that we're not the parent of the second child. */ exit(0); }在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用 waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是root身份kill-9也不能杀死僵尸进程。补救办法是杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为”孤儿进程”,过继给1号进程init,init会定期调用wait回收清理这些父进程已退出的僵尸子进程。
所以,上面的示例可以改成:
<"pcntl_fork")){ //生成第一个子进程 $pid = pcntl_fork(); //$pid即所产生的子进程id if($pid == -1){ //子进程fork失败 die('could not fork'); }else{ if($pid){ //父进程code sleep(5); //等待5秒 exit(0); //或$this->_redirect('/'); }else{ //第一个子进程code //产生孙进程 if(($gpid = pcntl_fork()) < 0){ ////$gpid即所产生的孙进程id //孙进程产生失败 die('could not fork'); }elseif($gpid > 0){ //第一个子进程code,即孙进程的父进程 $status = 0; $status = pcntl_wait($status); //阻塞子进程,并返回孙进程的退出状态,用于检查是否正常退出 if($status ! = 0) file_put_content('filename', '孙进程异常退出'); //得到父进程id //$ppid = posix_getppid(); //如果$ppid为1则表示其父进程已变为init进程,原父进程已退出 //得到子进程id:posix_getpid()或getmypid()或是fork返回的变量$pid //kill掉子进程 //posix_kill(getmypid(), SIGTERM); exit(0); }else{ //即$gpid == 0 //孙进程code //.... //结束孙进程(即当前进程),以防止生成僵尸进程 if(function_exists('posix_kill')){ posix_kill(getmypid(), SIGTERM); }else{ system('kill -9'. getmypid()); } exit(0); } } } }else{ // 不支持多进程处理时的代码在这里 } //..... "htmlcode"><"htmlcode"><?php //Action代码 public function createAction(){ //.... //将args替换成要传给insertLargeData.php的参数,参数间用空格间隔 system('nohup php -f insertLargeData.php ' . ' args ' . '&'); $this->redirect('/'); } ?>你还可以使用screen命令代替nohup命令。
DDR爱好者之家 Design By 杰米广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!DDR爱好者之家 Design By 杰米暂无评论...《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
2025年02月23日2025年02月23日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]