当前位置: 首页 > news >正文

PHP多进程编程与进程管理

PHP多进程编程与进程管理

PHP的pcntl扩展提供了多进程编程的能力。虽然Web开发中用得不多,但在CLI模式下多进程可以并行处理大量任务。

pcntl_fork创建子进程。父进程和子进程在fork之后各自执行不同的代码路径。

```php
// 检查pcntl扩展
if (!extension_loaded('pcntl')) {
die("pcntl扩展未安装。\n");
}

if (!extension_loaded('posix')) {
die("posix扩展未安装。\n");
}

echo "父进程 PID: " . posix_getpid() . "\n";

$pid = pcntl_fork();

if ($pid == -1) {
die("fork失败\n");
} elseif ($pid == 0) {
// 子进程
echo "子进程 PID: " . posix_getpid() . ", 父进程 PID: " . posix_getppid() . "\n";
for ($i = 0; $i < 3; $i++) {
echo "子进程工作... {$i}\n";
sleep(1);
}
exit(0);
} else {
// 父进程
echo "创建了子进程 PID: $pid\n";
echo "父进程继续工作\n";
pcntl_wait($status); // 等待子进程结束
echo "子进程已结束\n";
}
?>
```

多进程并行处理任务,可以充分利用多核CPU:

```php
function parallelProcess(array $tasks, int $workerCount = 4): void
{
$chunks = array_chunk($tasks, ceil(count($tasks) / $workerCount));
$children = [];

foreach ($chunks as $chunkId => $taskList) {
$pid = pcntl_fork();

if ($pid == -1) {
die("fork失败\n");
} elseif ($pid == 0) {
// 子进程
echo "Worker $chunkId (PID: " . posix_getpid() . ") 开始处理 " . count($taskList) . " 个任务\n";

foreach ($taskList as $task) {
echo "Worker $chunkId 处理: $task\n";
sleep(1);
}

echo "Worker $chunkId 完成\n";
exit(0);
} else {
$children[] = $pid;
}
}

// 父进程等待所有子进程
foreach ($children as $pid) {
pcntl_waitpid($pid, $status);
echo "子进程 $pid 已退出\n";
}

echo "所有任务处理完成\n";
}

$tasks = range(1, 20);
parallelProcess($tasks, 4);
?>
```

进程池可以控制并发数量,避免一次性创建太多进程:

```php
class ProcessPool
{
private int $maxWorkers;
private array $workers = [];
private int $nextId = 0;

public function __construct(int $maxWorkers = 4)
{
$this->maxWorkers = $maxWorkers;
}

public function submit(callable $task, array $args = []): int
{
$this->waitForSlot();

$pid = pcntl_fork();

if ($pid == -1) {
throw new RuntimeException("fork失败");
} elseif ($pid == 0) {
// 子进程
exit($task(...$args) ? 0 : 1);
} else {
$id = $this->nextId++;
$this->workers[$pid] = $id;
echo "任务 #$id 已提交 (PID: $pid)\n";
return $id;
}
}

public function wait(): void
{
while (!empty($this->workers)) {
$pid = pcntl_wait($status);
if ($pid > 0 && isset($this->workers[$pid])) {
$id = $this->workers[$pid];
$exitCode = pcntl_wexitstatus($status);
echo "任务 #$id 完成 (PID: $pid, 退出码: $exitCode)\n";
unset($this->workers[$pid]);
}
}
}

private function waitForSlot(): void
{
while (count($this->workers) >= $this->maxWorkers) {
$pid = pcntl_wait($status);
if ($pid > 0 && isset($this->workers[$pid])) {
unset($this->workers[$pid]);
}
}
}

public function getActiveCount(): int
{
return count($this->workers);
}

public function __destruct()
{
$this->wait();
}
}

$pool = new ProcessPool(3);

for ($i = 1; $i <= 10; $i++) {
$pool->submit(function ($id) {
$pid = posix_getpid();
echo "进程 $pid 执行任务 #$id\n";
sleep(rand(1, 3));
return true;
}, [$i]);
}

$pool->wait();
echo "全部完成\n";
?>
```

进程间通信用消息队列或共享内存:

```php
// 简单消息队列
class MessageQueue
{
private int $queue;
private int $msgType = 1;

public function __construct(string $path, int $project)
{
$key = ftok($path, $project);
if ($key === -1) {
throw new RuntimeException("ftok失败");
}
$this->queue = msg_get_queue($key);
if ($this->queue === false) {
throw new RuntimeException("获取消息队列失败");
}
}

public function send(mixed $message): bool
{
return msg_send($this->queue, $this->msgType, serialize($message));
}

public function receive(): mixed
{
$message = null;
$success = msg_receive($this->queue, 0, $this->msgType, 65536, $message);
return $success ? unserialize($message) : null;
}

public function remove(): void
{
msg_remove_queue($this->queue);
}

public function stats(): array
{
$stats = msg_stat_queue($this->queue);
return [
'messages' => $stats['msg_qnum'],
'bytes' => $stats['msg_qbytes'],
];
}
}
?>
```

多进程编程在PHP中需要注意几个问题。子进程会继承父进程的文件描述符和数据库连接,需要小心处理。进程退出前要清理资源。信号处理要做好,避免出现僵尸进程。总的来说,多进程是PHP CLI编程中的重要工具,适合数据采集、日志处理、批量计算等场景。

http://www.jsqmd.com/news/945482/

相关文章:

  • 2026年6月永州职业高中选型技术推荐与实测盘点:永州中等专业学校/永州民办中专学校/永州职业技术学校/优选推荐 - 优质品牌商家
  • FreeRTOS 手动移植教程(三):任务延时与时间管理——从裸机 delay 到 vTaskDelayUntil
  • 【无人机控制】基于matlab无人机分布式控制算法研究助力UGV追踪地面目标【含Matlab源码 15592期】
  • 解锁B站缓存:革新你的视频珍藏方式
  • Win11上VMware Workstation 17 Pro虚拟机频繁崩溃?别急着重装,试试这4个亲测有效的修复方法
  • 如何安全备份你的QQ空间数字记忆:GetQzonehistory完整指南
  • 智能测试落地失败率高达68%?(2023年Gartner实测数据深度复盘)
  • 5分钟快速上手:FanControl终极Windows风扇管理完整指南
  • 为什么Alice-Tools是AliceSoft游戏爱好者的终极工具箱?[特殊字符]
  • 智能任务超时熔断机制缺失导致成本飙升217%?5个生产环境真实Case与实时决策树模型
  • BarrageGrab:WebSocket直连技术重构直播弹幕数据采集架构
  • Modern Fortran扩展深度解析:架构揭秘与高性能计算开发新范式
  • 如何将任天堂Joy-Con变成Windows上的Xbox手柄?XJoy开源方案完全指南
  • 终极抖音视频下载指南:如何一键批量下载无水印高清内容
  • DIY蓝牙耳机改造指南:从有线到无线的核心步骤与避坑要点
  • 5步告别激活烦恼:KMS_VL_ALL_AIO智能激活脚本完全指南
  • 如何用AI视觉助手重塑你的桌面工作流:终极跨平台自动化指南
  • 告别Kali黑屏噩梦:深度解析LightDM/GDM3显示管理器冲突与Xorg配置修复
  • 基于Arduino与GRBL的桌面数控写字机DIY全攻略
  • WSA-Pacman完全指南:5分钟掌握Windows安卓应用管理终极方案
  • 如何彻底解决显卡驱动问题:Display Driver Uninstaller完全指南
  • 从Prompt日志到行为图谱:构建可审计、可回溯、可归因的智能反馈整合体系(含ISO/IEC 23894合规检查清单)
  • 终极项目管理指南:用GanttProject实现高效项目规划与跟踪
  • 3个核心技巧:如何用SI6 Networks IPv6 Toolkit提升网络安全评估效率
  • c# solidworks 自动标注折弯7 图可视化,清晰定义,画点改画线
  • 3个让你爱上Windows APK安装器的颠覆性体验
  • 一文搞定Java面试:设计模式实战应用与案例分析
  • 我为了写这个功能已花了cursor上亿token了,怎么评价,效果暂时没啥问题
  • 3分钟掌握Illustrator智能填充:Fillinger插件终极指南
  • 【限时解密】头部金融科技公司AI任务编排内参(含12类异构API适配器源码+任务血缘图谱生成脚本)