我有一个在 Ubuntu linux 机器上运行的 PHP 脚本。该脚本使用该函数生成多个进程pcntl_fork()
,并使用该pcntl_waitpid()
函数记录它们被杀死。它经常产生这些(我估计大约 40-50/秒),但是这些进程都被立即杀死(我已经尝试exit()
过posix_kill(${pid}, SIGKILL)
,无济于事)。该脚本可以正常工作几秒钟(取决于 10~30 秒),但不可避免地会停止并停止创建“子”进程。由于脚本导致的机器上的内存使用量没有增加,但是当脚本停止时,机器上的 cpu 会慢慢飙升,直到我用 Ctrl-C 强制终止脚本。每个进程都旨在解析一行文本并最终将其保存到文件中。出于测试目的,我只是在创建子进程后立即退出它们。在一项测试中,大约 1400 个进程在脚本冻结之前成功启动并终止,尽管就像我说的那样。
我知道一台机器有一个 ulimit,但我相信我读到它限制了并发进程的数量。由于此脚本在创建子进程后立即将其杀死,因此我对正在发生的事情感到困惑。这是我当前的 ulimit 配置 ( ulimit -a
) 的输出:
核心文件大小(块,-c)0 数据段大小 (kbytes, -d) 无限制 调度优先级 (-e) 0 文件大小(块,-f)无限制 待处理信号 (-i) 29470 最大锁定内存 (kbytes, -l) 64 最大内存大小 (kbytes, -m) 无限制 打开文件 (-n) 1024 管道大小(512 字节,-p)8 POSIX 消息队列(字节,-q)819200 实时优先级 (-r) 0 堆栈大小(千字节,-s)8192 cpu时间(秒,-t)无限制 最大用户进程 (-u) 29470 虚拟内存 (kbytes, -v) 无限制 文件锁 (-x) 无限制
PHP 中是否有一个全局限制来确定脚本执行期间创建的进程总数?**请记住,这些子进程会立即被杀死,所以我不认为这是创建无限数量的进程窃取系统资源的问题。
这是一些源代码:
我用这个初始化叉子
$this->process_control->fork(array($this, "${FUNCTION_NAME}"), array(STRING_LINE), false);
进程分叉函数。在这种情况下,$callback 是要在适当的类中调用的函数的名称。$params 是要传递给 $callback 中指定的函数的参数数组。
公共函数 fork ($callback, $params = null, $hang = true) { $this->logger->write_log('log', "进入fork函数!"); // 评估分叉的返回值 开关 ($pid = pcntl_fork()) { case -1: // 失败 $this->logger->write_log('error', "Could not fork!"); 退出(1); 休息; case 0: // 子节点创建成功 $this->logger->write_log('log', "进入子函数!"); $this->logger->write_log('log', 'child' . posix_getpid() . 'started'); 如果(空($回调)){ $this->logger->write_log('warn', "回调为空,无事可做!"); 退出(1); } if (is_array($callback) && is_array($params)) { if (!call_user_func_array($callback, $params)) { $this->logger->write_log('error', "守护进程返回假!"); 退出(1); } 别的 { 退出(0); } } 别的 { if (!call_user_func($callback, $params)) { $this->logger->write_log('error', "守护进程返回假!"); 退出(1); } 别的 { 退出(0); } } 休息; 默认值://父级 $this->logger->write_log('log', "进入父函数!"); 如果 ($hang != true) { $this->wait($pid, false); } 别的 { $this->wait($pid); } 休息; } } 公共函数等待($p_id,$hang = true) { 如果($挂){ $pid = pcntl_waitpid($p_id, $status); } 别的 { $pid = pcntl_waitpid($p_id, $status, WNOHANG); } 开关($pid){ 情况1: 案例0: $this->logger->write_log('log', "child exited"); 休息; 默认: $this->logger->write_log('log', "child $pid exited"); 休息; } }
实际处理文本行的函数。文本行是 JSON 对象:
公共函数 FUNCTION_NAME($line) { $this->logger->write_log('info', '进入 FUNCTION_NAME 函数'); $start_time = 微时间(真); 尝试 { # 检查 JSON 行是否格式错误 $line_array = json_decode($line, true); if (!isset($line_array)) { throw new Exception('无法成功处理行'); } # 将内容保存到磁盘 if (!file_put_contents(FILE_NAME, $line, LOCK_EX)) { throw new Exception('文件无法保存'); } $this->logger->write_log('info', '保存的行'); 返回真; } 捕捉(异常 $e){ $this->logger->write_log('error', $e->getMessage()); $this->logger->write_log('error', '------------------------------------ ----------------'); $this->logger->write_log('error', var_export($line, true)); $this->logger->write_log('error', '------------------------------------ ----------------'); file_put_contents(ERROR_SRC_FILE, $line, FILE_APPEND); 返回假; } }
抱歉,如果代码太多,请告诉我任何问题