我有一个在 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);
返回假;
}
}
抱歉,如果代码太多,请告诉我任何问题