文章目录
pcntl
pcntl_signal
信号注册函数
pcntl_alarm
- 指定秒数中断程序执行任务。
- 每次执行只会有一个定时器生效,若之前计时器还没结束就定义新定时器,会替代之前定时器并返回之前定时器结束前秒数,若之前计时器已完成返回0
- 参数设为0,会清空当前所有定时器,并不发起调用
- 定时器会中断系统,即便是sleep执行中
<?php
declare(ticks = 1);
function signal_handler($signal) {
print "Caught SIGALRM\n";
echo pcntl_alarm(3).PHP_EOL;//再次调用
}
pcntl_signal(SIGALRM, "signal_handler", true);
echo pcntl_alarm(5).PHP_EOL;//只会调用一次
echo pcntl_alarm(3).PHP_EOL;//提示5,因为上一个计时器完成还剩5s
while(1) {
//
}
?>
pcntl_fork
创建子进程
- unix创建进程效率要比线程高,但需考虑进程数和内存等限制
<?php
$pid = pcntl_fork();
switch($pid) {
case -1:
print "Could not fork!\n";
exit;
case 0://子进程
print "In child!\n";
break;
default://父进程,值代表子进程PID
print "In parent!\n";
}
?>
pcntl_waitpid
等待或返回fork的子进程状态
挂起当前进程的执行直到参数pid指定的进程号的进程退出, 或接收到一个信号要求中断当前进程或调用一个信号处理函数。
如果pid指定的子进程在此函数调用时已经退出(俗称僵尸进程),此函数 将立刻返回。
pid可选值
- 小于-1 等待任意进程组ID等于参数pid给定值的绝对值的进程。
- -1 等待任意子进程;与pcntl_wait函数行为一致。
- 0 等待任意与调用进程组ID相同的子进程。
- 大于0 等待进程号等于参数pid值的子进程。
options
- WNOHANG 如果没有子进程退出立刻返回。
- WUNTRACED 子进程已经退出并且其状态未报告时返回。
pcntl_wexitstatus
检查状态代码是否代表一个正常的退出。
- 进程共享内容
<?php
for ($i = 1; $i <= 5; ++$i) {
$pid = pcntl_fork();
if (!$pid) {
sleep(1);
print "In child $i\n";
exit($i);
}
}
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed\n";
}
?>
SIGCHLD: 父进程不阻塞
SIGCHLD信号会在一个或多个子进程结束时向父进程通知
此时再加上pcntl_waitpid loop来让父进程及时回收全部结束的子进程
<?php
declare(ticks = 1);
pcntl_signal(SIGCHLD, "signal_handler");
function signal_handler($signal) {
switch($signal) {
case SIGCHLD:
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed\n";
}
exit;
}
}
for ($i = 1; $i <= 5; ++$i) {
$pid = pcntl_fork();
if (!$pid) {
sleep(3);
print "In child $i\n";
exit($i);
}
}
while(1) {
//下面的代码会在父进程执行
echo "parent processing here".PHP_EOL;
sleep(1);
}
?>
pcntl_exec
调用程序执行,并取代自身
<?php
print "Before\n";
pcntl_exec("/usr/bin/uptime");
//下边不会输出
print "After\n";
?>
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com 本文链接 : https://newbmiao.github.io/2015/10/25/how-to-use-php-signal.html