当前位置: 首页 > 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.zskr.cn/news/1456961.html

相关文章:

  • 5分钟快速上手:FanControl终极Windows风扇管理完整指南
  • 为什么Alice-Tools是AliceSoft游戏爱好者的终极工具箱?[特殊字符]
  • 终极抖音视频下载指南:如何一键批量下载无水印高清内容
  • Modern Fortran扩展深度解析:架构揭秘与高性能计算开发新范式
  • BarrageGrab:WebSocket直连技术重构直播弹幕数据采集架构
  • WSA-Pacman完全指南:5分钟掌握Windows安卓应用管理终极方案
  • 如何彻底解决显卡驱动问题:Display Driver Uninstaller完全指南
  • 一文搞定Java面试:设计模式实战应用与案例分析
  • 3分钟掌握Illustrator智能填充:Fillinger插件终极指南
  • 3大核心功能解锁:Vectorizer图片无损放大与PNG转SVG的终极指南
  • 如何高效批量下载抖音视频:专业工具的完整指南
  • Windows右键菜单终极优化:3步让系统响应速度提升85%的完整指南
  • 5分钟快速搭建OpenSign:免费开源的DocuSign替代方案
  • Android平台上的统一SDR驱动架构:rtl_tcp_andro的技术实现与应用生态
  • 智能胎心监护系统:移动医疗硬件与App协同架构全解析
  • Python为何成为TVA的神经与感官系统(10)
  • Windows 11终极优化指南:用Win11Debloat一键清理系统,提升51%性能
  • PHM2012轴承振动数据上手即用的RUL预测代码包:含预处理、CNN-LSTM建模、评估与可视化全流程
  • PHP命名参数与构造器提升详解
  • 微信小程序直连阿里云IoT控制家电+实时显示温湿度/PM2.5数据源码
  • 模型准确率下降却无告警?——用3类动态基线+5维监控维度重建AI可信度防线
  • 降AIGC黑科技揭秘!AI率92%暴降至5%!实测10款降AIGC平台!免费额度狂薅攻略
  • 2026年速冻蔬菜批发供应商推荐榜单:南通/海门/江苏出口级IQF BQF速冻蔬菜,预制菜食堂餐饮及日产能140吨优质厂家精选 - 品牌企业推荐师(官方)
  • AI工具如何真正接管排班?揭秘头部企业已验证的7步集成路径与ROI提升217%的关键数据
  • 出海物联网设备全球网络准入架构:基于Python的自动APN适配与链路保活实战
  • 如何在电脑上轻松编辑PDF | 最新指南
  • 超越教程:用UE4 Niagara模块化思维,拆解并重组你的爆炸、火焰与烟雾特效
  • 2026年成都镀锌楼承板厂家TOP5排行与选型指南:‌成都彩钢瓦厂家电话/‌成都彩钢瓦厂家直销电话/‌成都组合楼承板厂家推荐/选择指南 - 优质品牌商家
  • 2026年实测10款AI智能降重工具推荐:免费与付费全对比,毕业论文降低ai率必看
  • 2026 成都卫生间漏水、外墙、楼顶、地下室、阳光房渗漏维修师傅推荐|同城附近上门防水补漏公司测评 - 防水百科