多进程
# pcntl_fork
- 此函数只能在Linux下使用,而且需要安装pcntl的扩展
- pcntl_fork()函数执行的时候,会创建一个子进程。子进程会复制当前进程,也就是父进程的所有数据,代码,还有状态;
- 创建子进程成功后,在父进程内,返回子进程号,在子进程内返回0,失败则返回-1;
案例:
// 进程数
$forkNum = 3;
// 进程号记录
$pids = [];
$pageNum = 1;
echo '程序开始' . PHP_EOL;
for ($i = 0; $i < $forkNum; $i++) {
$pid = pcntl_fork(); // 创建子进程;子进程代码完全复制(此时的)父进程,包括变量状态
if ($pid) {
echo '子进程创建成功:' . $i . ' - ' . $pid . PHP_EOL;
$pageNum += 1;
$pids[] = $pid;
echo '子进程号:' . $pid . ' 已记录;' . PHP_EOL;
} elseif ($pid == 0) {
// sleep(2);
echo '这里是第 ' . $i . ' 个子进程内部' . PHP_EOL;
echo 'pageNum值为: ' . $pageNum . PHP_EOL;
$pageNum = $pageNum * 2; // 并不会影响到别的进程此变量
echo '第 ' . $i . ' 个子进程完成任务; exit;' . PHP_EOL . PHP_EOL;
exit(); // 执行完,一定要结束,不然就会走进创建子进程的死循环
} else {
echo '创建子进程 ' . $i . ' 异常' . PHP_EOL;
}
}
// 检查所有子进程状态
foreach ($pids as $pid) {
// $res = pcntl_waitpid($pid, $status, WNOHANG); // WNOHANG 子进程没有退出的话 立马返回 0;使用这个的话就需要定时轮询反复检查状态
// 等待指定pid的进程完成
$res = pcntl_waitpid($pid, $status);
if ($res == -1 || $res > 0) {
if (!pcntl_wifexited($status)) {
// 进程非正常退出
echo "进程: $pid 非正常退出" . PHP_EOL;
} else {
// 获取进程终端的退出状态码;
$code = pcntl_wexitstatus($status);
echo "进程: $pid 已退出, 退出状态码为: $code" . PHP_EOL;
}
if (pcntl_wifsignaled($status)) {
// 不是通过接受信号中断
echo "进程: $pid 已退出, 但不是通过接受信号中断" . PHP_EOL;
} else {
$signal = pcntl_wtermsig($status);
echo "进程: $pid 已退出, 是通过接受信号而中断的" . PHP_EOL;
}
}
}
输出
程序开始
子进程创建成功:0 - 288
子进程号:288 已记录;
这里是第 0 个子进程内部
pageNum值为: 1
第 0 个子进程完成任务; exit;
子进程创建成功:1 - 289
子进程号:289 已记录;
子进程创建成功:2 - 290
子进程号:290 已记录;
这里是第 1 个子进程内部
pageNum值为: 2
第 1 个子进程完成任务; exit;
这里是第 2 个子进程内部
pageNum值为: 3
第 2 个子进程完成任务; exit;
进程: 288 已退出, 退出状态码为: 0
进程: 288 已退出, 是通过接受信号而中断的
进程: 289 已退出, 退出状态码为: 0
进程: 289 已退出, 是通过接受信号而中断的
进程: 290 已退出, 退出状态码为: 0
进程: 290 已退出, 是通过接受信号而中断的
上次更新: 2022/11/11, 14:40:53