php有一组进程掌握函数PCNTL,使得php能在nix系统中实现跟c一样的创建子进程、利用exec函数实行程序、处理旗子暗记等功能。
把稳:pcntl这个扩展仅在cli/cgi模式下可用。mod_php和php-fpm中不可以利用。在web server环境中不要利用这组函数,由于会导致不可预见的结果。另,windows作为非类unix系统,没有这些函数。
PCNTL 利用ticks来作为旗子暗记处理机制(signal handle callback mechanism),可以最小程度地降落处理异步事宜时的负载。何谓ticks?Tick 是一个在代码段中阐明器每实行 N 条低级语句就会发生的事宜,这个代码段须要通过declare来指定。
下面是一个隔5秒发送一个SIGALRM旗子暗记,并由signal_handler函数获取,然后打印一个“Caught SIGALRM”的例子:
<?php
declare(ticks = 1);
function signal_handler($signal) {
print \"大众Caught SIGALRM/n\"大众;
pcntl_alarm(5);
}
pcntl_signal(SIGALRM, \公众signal_handler\"大众, true);
pcntl_alarm(5);
while(true){
}
?>
实在官方的pcntl_signal性能极差,紧张是PHP的函数无法直接注册到操作系统旗子暗记设置中,以是pcntl旗子暗记须要依赖tick机制来完成。 pcntl_signal的实现事理是,触发旗子暗记后先将旗子暗记加入一个行列步队中。然后在PHP的ticks回调函数中不断检讨是否有旗子暗记,如果有旗子暗记就实行PHP中指定的回调函数,如果没有则跳出函数。 ticks=1表示每实行1行PHP代码就回调此函数。实际上大部分韶光都没有旗子暗记产生,但ticks的函数一贯会实行。 比较好的做法是去掉ticks,转而利用pcntl_signal_dispatch,在代码循环中自行处理旗子暗记。
pcntl_signal_dispatch的实现
<?php
// 定义一个处理器,吸收到SIGINT旗子暗记后只输出一行信息
function signalHandler($signo) {
switch ($signo) {
case SIGUSR1: echo \公众SIGUSR1\n\"大众; break;
case SIGUSR2: echo \"大众SIGUSR2\n\"大众; break;
default: echo \公众unknow\"大众; break;
}
}
//安装旗子暗记触发器器
pcntl_signal(SIGINT, 'signalHandler');
while (true) {
sleep(1);
posix_kill(posix_getpid(), SIGUSR1);///向当提高程发送SIGUSR1旗子暗记
pcntl_signal_dispatch(); //吸收到旗子暗记时,调用注册的signalHandler()
}
PCNTL的函数:旗子暗记处理
int pcntl_alarm ( int $seconds )
设置一个$seconds秒后发送SIGALRM旗子暗记的计数器
bool pcntl_signal(int $signo ,callback $handler [,bool $restart_syscalls=true])
为$signo设置一个处理该旗子暗记的回调函数
第一个参数是旗子暗记编号 第二个参数是旗子暗记发生时回调的PHP函数。 第三个参数是是否restart,是否重新注册此旗子暗记。这个参数如果为false,那此旗子暗记只注册处理一次。
把稳:每次对 pcntl_alarm()的调用都会取消之前设置的alarm旗子暗记和sleep()函数。
下面是一个隔5秒发送一个SIGALRM旗子暗记,并由signal_handler函数获取,然后打印一个“Caught SIGALRM”的例子:
<?php
declare(ticks = 1);
function signal_handler($signal) {
print \公众Caught SIGALRM/n\公众;
pcntl_alarm(5);
}
pcntl_signal(SIGALRM, \"大众signal_handler\公众, true);
pcntl_alarm(5);
for(;;) {
}
?>
实行程序
void pcntl_exec ( string $path [, array $args [, array $envs ]] )
在当前的进程空间中实行指定程序,类似于c中的exec族函数。所谓当前空间,即载入指定程序的代码覆盖掉当提高程的空间,实行完该程序进程即结束。
<?php
$dir = '/home/test/';
$cmd = 'ls';
$option = '-l';
$pathtobin = '/bin/ls';
$arg = array($cmd, $option, $dir);
pcntl_exec($pathtobin, $arg);
echo '123'; //不会实行到该行
?>
创建进程
int pcntl_fork ( void ) 为当提高程创建一个子进程
int pcntl_wait ( int &$status [, int $options ] ) 壅塞当提高程,只到当提高程的一个子进程退出或者收到一个结束当提高程的旗子暗记。
int pcntl_waitpid ( int $pid , int &$status [, int $options ] ) 功能同pcntl_wait,差异为waitpid为等待指定pid的子进程。当pid为-1时pcntl_waitpid与pcntl_wait一样。
在 pcntl_wait和pcntl_waitpid两个函数中的$status中存了子进程的状态信息,这个参数可以用于 pcntl_wifexited、pcntl_wifstopped、pcntl_wifsignaled、pcntl_wexitstatus、 pcntl_wtermsig、pcntl_wstopsig、pcntl_waitpid这些函数。
举个例子
<?php
$pid = pcntl_fork();
if($pid) {
pcntl_wait($status);
$id = getmypid();
echo \公众parent process,pid {$id}, child pid {$pid}/n\"大众;
} else {
$id = getmypid();
echo \"大众child process,pid {$id}/n\公众;
sleep(2);
}
?>
子进程在输出child process等字样之后sleep了2秒才结束,而父进程壅塞着直到子进程退出之后才连续运行。
进程优先级
int pcntl_getpriority ([ int $pid [, int $process_identifier ]] ) 取得进程的优先级,即nice值,默认为0。不同的系统类型以及内核版本下 优先级可能不同(手册中为-20到20)
bool pcntl_setpriority ( int $priority [, int $pid [, int $process_identifier ]] ) 设置进程的优先级
以上便是php如何处理进程旗子暗记(附实例)的详细内容