时间:2023-05-26 16:57:01 | 来源:网站运营
时间:2023-05-26 16:57:01 来源:网站运营
PHP多进程编程~(一):[root@bogon downloads]# cd php-7.1.1/ext/pcntl[root@bogon pcntl]# php -i | grep configureConfigure Command => './configure' '--prefix=/usr/local/php/' '--enable-mbstring' '--with-curl' '--with-gd' '--enable-fpm' '--enable-mysqlnd' '--with-pdo-mysql=mysqlnd' '--with-config-file-path=/usr/local/php71/etc/' '--with-mysqli=mysqlnd'[root@bogon pcntl]# /usr/local/php/bin/phpize Configuring for:PHP Api Version: 20160303Zend Module Api No: 20160303Zend Extension Api No: 320160303[root@bogon pcntl]# ./configure --enable-pcntl --with-php-config=/usr/local/php/bin/php-config ......creating libtoolappending configuration tag "CXX" to libtoolconfigure: creating ./config.statusconfig.status: creating config.h[root@bogon pcntl]# make && make install......Build complete.Don't forget to run 'make test'.Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20160303/#修改配置文件,添加pcntl扩展[root@bogon pcntl]# vim /usr/local/php/etc/php.iniextension=pcntl.so
[root@bogon pcntl]# php -m | grep pcntlpcntl
※shmop安装同pcntl$pid = pcntl_fork();var_dump($pid);
[root@bogon multiprocess]# php test.php #会有两个值返回int(55777)int(0)
$pid = pcntl_fork();switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; break; default: echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break;}
[root@bogon multiprocess]# php test.php I'm the parent process: 55806 and $pid=55807I'm the child process: 55807 and $pid=0
[root@bogon multiprocess]# vim test.php<?phpecho "Master process id: " . posix_getpid() . PHP_EOL;sleep(10);
[root@bogon multiprocess]# php test.php Master process id: 51688[root@bogon html]# ps -ef | grep test.phproot 51688 36864 0 02:00 pts/5 00:00:00 php test.php #可以看到进程ID为51688
<?php$pid = pcntl_fork();switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process " . posix_getpid() . PHP_EOL; break; default: echo "I'm the parent process " . posix_getpid() . PHP_EOL; break;}sleep(100);
[root@bogon multiprocess]# php test.php I'm the parent process: 55715I'm the child process: 55716#为什么看上去程序中互斥的两个分支都被执行了,在一个程序的一次执行中,这当然是不可能的,事实上你看到的两行输出是来自两个独立的进程,而这两个进程来自同一个程序的两次执行。[root@bogon html]# ps auxf | grep test.phproot 55715 0.0 1.1 222784 12128 pts/8 S+ 01:01 0:00 /_ php test.phproot 55716 0.0 0.5 222784 5444 pts/8 S+ 01:01 0:00 /_ php test.php
※fork之后,操作系统会复制一个与父进程完全相同的子进程,虽说是父子关系,但是在操作系统看来,他们更像兄弟关系,这2个进程共享代码空间, 但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,但只有一点不同,如果fork成功,子进程中fork的返回值是0, 父进程中fork的返回值是子进程的进程号,如果fork失败,父进程会返回错误。 可以这样想象,2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了,这也是fork为什么叫fork的原因。 至于哪一个进程最先运行,这与操作系统平台的调度算法有关,而且这个问题在实际应用中并不重要,如果需要父子进程协同运作,可以通过控制语法结构的办法解决。#vim exe.php$pid = pcntl_fork();switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; //exec("sh /home/multiprocess/test.sh A B");//执行完之后后面逻辑继续执行 pcntl_exec("/home/multiprocess/test.sh",["A","B"]);//执行完之后,后面逻辑不再执行 break; default: echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break;}
#vim test.sh#!/bin/bashecho $1 >> /home/multiprocess/test.logecho $2 >> /home/multiprocess/test.log
#vim monitor.php<?php$child = [];function forkPro(){ global $child; echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break; }}forkPro();sleep(10);
[root@bogon multiprocess]# php monitor.php Master process id: 60368I'm the parent process: 60368 and $pid=60369十秒钟后,父进程退出,子进程继续运行...I'm the child process: 60369 and $pid=0......[root@bogon multiprocess]#
[root@bogon multiprocess]# ps auxf | grep monitor.phproot 60371 0.0 0.0 103324 844 pts/10 S+ 19:48 0:00 | /_ grep monitor.phproot 60369 0.0 0.5 222784 5388 pts/11 S 19:48 0:00 php monitor.php #子进程还在继续运行
#vim monitor.php<?php$child = [];function forkPro(){ global $child; echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break; }}//创建多个子进程for($i = 0;$i < 5;$i++){ forkPro();}echo "十秒钟后,父进程退出,子进程继续运行..." . PHP_EOL;sleep(10);
Master process id: 60586I'm the child process: 60587 and $pid=0I'm the parent process: 60586 and $pid=60587Master process id: 60586I'm the parent process: 60586 and $pid=60588Master process id: 60586I'm the parent process: 60586 and $pid=60589Master process id: 60586I'm the child process: 60588 and $pid=0I'm the child process: 60590 and $pid=0I'm the child process: 60589 and $pid=0I'm the parent process: 60586 and $pid=60590Master process id: 60586I'm the parent process: 60586 and $pid=60591十秒钟后,父进程退出,子进程继续运行...I'm the child process: 60591 and $pid=0......[root@bogon multiprocess]#
[root@bogon multiprocess]# ps auxf | grep monitorroot 60607 0.0 0.0 103324 828 pts/10 S+ 22:32 0:00 | /_ grep monitorroot 60587 0.0 0.5 222784 5384 pts/11 S 22:28 0:00 php monitor.phproot 60588 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60589 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60590 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60591 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.php
#可以看到命令“grep monitor”也被打印了出来,不完美[root@bogon multiprocess]# ps auxf | grep monitorroot 60607 0.0 0.0 103324 828 pts/10 S+ 22:32 0:00 | /_ grep monitorroot 60587 0.0 0.5 222784 5384 pts/11 S 22:28 0:00 php monitor.phproot 60588 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60589 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60590 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60591 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.php
#使用“grep -v grep”就过滤了命令行[root@bogon multiprocess]# ps auxf | grep monitor | grep -v greproot 60587 0.0 0.5 222784 5384 pts/11 S 22:28 0:00 php monitor.phproot 60588 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60589 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60590 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.phproot 60591 0.0 0.5 222784 5380 pts/11 S 22:28 0:00 php monitor.php
[root@bogon multiprocess]# ps auxf | grep monitor | grep -v grep | awk '{print $2}'6058760588605896059060591
[root@bogon multiprocess]# ps auxf | grep monitor | grep -v grep | awk '{print $2}' | xargs kill -9
|管道符,用来隔开两个命令,管道符左边命令的输出会作为管道符右边命令的输入ps命令用来列出系统中当前运行的进程, ps -ef显示所有进程信息,联通命令行grep命令用于过滤/搜索特定字符,grep monitor在这里为搜索过滤所有含有“monitor”名称的进程 grep -v 显示不包含匹配文本的所有行,在这里为筛选出所有不包含grep名称的进程,对上一步的进程再做一次筛选(因为ps -ef列出了所有的命令,包括命令行) awk在文件或字符串中基于指定规则浏览和抽取信息。把文件逐行读入,以空格为默认分隔符将每行切片,然后再进行后序处理。这里利用awk '{print $2}'将上一步中过滤得到的进程进行打印,$2表示打印第二个域(PID,进程号) $0表示所有域,$1表示第一个域,$n表示第n个域。 xargs命令是给命令传递参数的过滤器,善于把标准数据数据转换成命令行参数。在这里则是将获取前一个命令的标准输出然后转换成命令行参数传递给后面的kill命令。
<?php$child = [];function forkPro(){ global $child; //echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm a child process: " . posix_getpid() . ' and input $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; echo "I'm a parent process: " . posix_getpid() .' and input $pid='.$pid .PHP_EOL; break; }}for($i = 0;$i < 3;$i++){ forkPro();}while(count($child)){ if(($exit_id = pcntl_wait($status)) > 0){ echo "有子进程退出,进程ID是:" . $exit_id . PHP_EOL; }}echo "Done...";
[root@bogon multiprocess]# php monitor.php I'm a parent process: 60876 and input $pid=60877I'm a parent process: 60876 and input $pid=60878I'm a child process: 60877 and input $pid=0I'm a child process: 60878 and input $pid=0I'm a parent process: 60876 and input $pid=60879I'm a child process: 60879 and input $pid=0有子进程退出,进程ID是:60879 #当kill -9 60879
<?php$child = [];function forkPro(){ global $child; //echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break; } } for($i = 0;$i < 3;$i++){ forkPro();}while(count($child)){ if(($exit_id = pcntl_wait($status)) > 0){ echo "有子进程退出,进程ID是:" . $exit_id . PHP_EOL; echo "被中断的子进程的信号值是:" . pcntl_wtermsig($status) . PHP_EOL; }}echo "done/n";
[root@bogon multiprocess]# php monitor.php I'm the parent process: 60933 and $pid=60934I'm the parent process: 60933 and $pid=60935I'm the parent process: 60933 and $pid=60936I'm the child process: 60934 and $pid=0I'm the child process: 60935 and $pid=0I'm the child process: 60936 and $pid=0有子进程退出,进程ID是:60936 #kill -9 60936被中断的子进程的信号值是:9 #会收到是什么操作导致了进程退出
#vim monitor.php<?php$child = [];function forkPro(){ global $child; //echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "I'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break; } } for($i = 0;$i < 3;$i++){ forkPro();}while(count($child)){ if(($exit_id = pcntl_wait($status)) > 0){ echo "有子进程退出,进程ID是:" . $exit_id . PHP_EOL; echo "被中断的子进程的信号值是:" . pcntl_wtermsig($status) . PHP_EOL; unset($child[$exit_id]);//从子进程集合中移除已经退出的子进程 } if(count($child) < 3){ //当集合中的子进程数量小于一定量时,自动fork新的子进程 forkPro(); }}echo "done/n";
[root@bogon multiprocess]# php monitor.php I'm the parent process: 61076 and $pid=61077I'm the parent process: 61076 and $pid=61078I'm the parent process: 61076 and $pid=61079I'm the child process: 61077 and $pid=0I'm the child process: 61078 and $pid=0I'm the child process: 61079 and $pid=0有子进程退出,进程ID是:61079被中断的子进程的信号值是:9I'm the parent process: 61076 and $pid=61084I'm the child process: 61084 and $pid=0
[root@bogon multiprocess]# ps auxf | grep monitor | grep -v grep | grep -v vimroot 61076 0.0 1.2 222784 12224 pts/9 S+ 02:04 0:00 | /_ php monitor.phproot 61077 0.0 0.5 222784 5468 pts/9 S+ 02:04 0:00 | /_ php monitor.phproot 61078 0.0 0.5 222784 5384 pts/9 S+ 02:04 0:00 | /_ php monitor.phproot 61079 0.0 0.5 222784 5384 pts/9 S+ 02:04 0:00 | /_ php monitor.php[root@bogon multiprocess]# kill -9 61079 #观察进程终止前后的变化[root@bogon multiprocess]# ps auxf | grep monitor | grep -v grep | grep -v vimroot 61076 0.0 1.2 222784 12232 pts/9 S+ 02:04 0:00 | /_ php monitor.phproot 61077 0.0 0.5 222784 5468 pts/9 S+ 02:04 0:00 | /_ php monitor.phproot 61078 0.0 0.5 222784 5384 pts/9 S+ 02:04 0:00 | /_ php monitor.phproot 61084 0.0 0.5 222784 5384 pts/9 S+ 02:05 0:00 | /_ php monitor.php #自动启动的新进程
※That's all,就已经完成了对子进程的监控和自动重启#vim daemon.php<?phpfunction daemon(){ global $child; //1.1 创建子进程 $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: //child //2、设置sid if(($sid = posix_setsid()) <= 0){ die("Set sid failed!/n"); } //3、改变目录 if(chdir('/') === false){ die("Change directory failed!/n"); } //4、更改为宽松掩码 umask(0); //5、关闭标准I/O fclose(STDIN); //fclose(STDOUT); //fclose(STDERR); break; default: //parent exit; break; }}daemon();$child = [];function forkPro(){ global $child; //echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "/nI'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; //echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break; }}for($i = 0;$i < 3;$i++){ forkPro();}while(count($child)){ if(($exit_id = pcntl_wait($status)) > 0){ echo "有子进程退出,进程ID是:" . $exit_id . PHP_EOL; echo "被中断的子进程的信号值是:" . pcntl_wtermsig($status) . PHP_EOL; unset($child[$exit_id]);//从子进程集合中移除已经退出的子进程 } if(count($child) < 3){ //当集合中的子进程数量小于一定量时,自动fork新的子进程 forkPro(); }}echo "done/n";
[root@bogon multiprocess]# php daemon.phpI'm the child process: 62746 and $pid=0I'm the child process: 62745 and $pid=0I'm the child process: 62747 and $pid=0
[root@bogon multiprocess]# ps auxf | grep daemon.php | grep -v grep | grep -v vimroot 62744 0.1 0.5 222780 5584 ? Ss 22:35 0:00 php daemon.phproot 62745 0.1 0.5 222780 5468 ? S 22:35 0:00 /_ php daemon.phproot 62746 0.0 0.5 222780 5468 ? S 22:35 0:00 /_ php daemon.phproot 62747 0.1 0.5 222780 5468 ? S 22:35 0:00 /_ php daemon.php
[root@bogon multiprocess]# kill 62746 62747[root@bogon multiprocess]# ps auxf | grep daemon.php | grep -v grep | grep -v vimroot 62744 0.0 0.5 222780 5712 ? Ss 22:35 0:00 php daemon.phproot 62745 0.0 0.5 222780 5468 ? S 22:35 0:00 /_ php daemon.phproot 62752 0.0 0.5 222780 5400 ? S 22:38 0:00 /_ php daemon.phproot 62753 0.0 0.5 222780 5400 ? S 22:38 0:00 /_ php daemon.php.........................................................[root@bogon multiprocess]# 有子进程退出,进程ID是:62746被中断的子进程的信号值是:15有子进程退出,进程ID是:62747被中断的子进程的信号值是:15I'm the child process: 62753 and $pid=0 #自动重启了进程I'm the child process: 62752 and $pid=0 #自动重启了进程
#退出终端,重新连接后发现进程依然存在[root@bogon multiprocess]# ps auxf | grep daemon.php root 62812 0.0 0.0 103324 844 pts/3 S+ 22:52 0:00 /_ grep daemon.phproot 62744 0.0 0.5 222780 5712 ? Ss 22:35 0:00 php daemon.phproot 62745 0.0 0.5 222780 5468 ? S 22:35 0:00 /_ php daemon.phproot 62752 0.0 0.5 222780 5400 ? S 22:38 0:00 /_ php daemon.phproot 62753 0.0 0.5 222780 5400 ? S 22:38 0:00 /_ php daemon.php
[root@bogon multiprocess]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+338) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+843) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-758) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX
[root@bogon multiprocess]# ps auxf | grep daemon.phproot 62993 0.0 0.0 103324 840 pts/5 S+ 00:34 0:00 /_ grep daemon.phproot 62744 0.0 0.5 222780 5712 ? Ss Dec26 0:00 php daemon.phproot 62745 0.0 0.5 222780 5468 ? S Dec26 0:00 /_ php daemon.phproot 62752 0.0 0.5 222780 5400 ? S Dec26 0:00 /_ php daemon.phproot 62753 0.0 0.5 222780 5400 ? S Dec26 0:00 /_ php daemon.php[root@bogon multiprocess]# ps --ppid 62744 # PID TTY TIME CMD62745 ? 00:00:00 php62752 ? 00:00:00 php62753 ? 00:00:00 php[root@bogon multiprocess]# ps --ppid 62744 | awk '/[0-9]/{print $1}'627456275262753
#vim signal.php<?phpfunction daemon(){ global $child; //1.1 创建子进程 $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: //child //2、设置sid if(($sid = posix_setsid()) <= 0){ die("Set sid failed!/n"); } //3、改变目录 if(chdir('/') === false){ die("Change directory failed!/n"); } //4、更改为宽松掩码 umask(0); //5、关闭标准I/O fclose(STDIN); //fclose(STDOUT); //fclose(STDERR); break; default: //parent exit; break; }}$sign = $_SERVER['argv'][1];switch($sign){ case 'start': if(file_exists('/tmp/masterPid')){ die("MasterPid already running!"); } break; case 'stop': $masterPid = file_get_contents('/tmp/masterPid'); exec("ps --ppid {$masterPid} | awk '/[0-9]/{print $1}'",$output,$status); if($status == 0){ print_r($output); } break; case 'reload': break; default: die("Please enter commond.../n"); break;}daemon();$child = [];$masterPid = posix_getpid();file_put_contents('/tmp/masterPid',$masterPid);//存放主进程IDfunction forkPro(){ global $child; //echo "Master process id: " . posix_getpid() . PHP_EOL; $pid = pcntl_fork(); switch($pid){ case -1: exit("Fork failed"); break; case 0: echo "/nI'm the child process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL; while(true) { sleep(3); } break; default: $child[$pid] = $pid; //echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL; break; }}for($i = 0;$i < 3;$i++){ forkPro();}while(count($child)){ if(($exit_id = pcntl_wait($status)) > 0){ echo "有子进程退出,进程ID是:" . $exit_id . PHP_EOL; echo "被中断的子进程的信号值是:" . pcntl_wtermsig($status) . PHP_EOL; unset($child[$exit_id]);//从子进程集合中移除已经退出的子进程 } if(count($child) < 3){ //当集合中的子进程数量小于一定量时,自动fork新的子进程 forkPro(); }}echo "done/n";
[root@bogon multiprocess]# php signal.php startI'm the child process: 64374 and $pid=0I'm the child process: 64375 and $pid=0I'm the child process: 64376 and $pid=0[root@bogon multiprocess]# ps auxf | grep signal.php | grep -v grep | grep -v vim root 64373 0.0 0.5 222780 5748 ? Ss 19:32 0:00 php signal.php startroot 64374 0.0 0.5 222780 5432 ? S 19:32 0:00 /_ php signal.php startroot 64375 0.0 0.5 222780 5432 ? S 19:32 0:00 /_ php signal.php startroot 64376 0.0 0.5 222780 5432 ? S 19:32 0:00 /_ php signal.php start[root@bogon tmp]# cat masterPid 64373
关键词:进程