1

我有一个在 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);
            返回假;
        }
    }

抱歉,如果代码太多,请告诉我任何问题

4

1 回答 1

1

要回答最初的问题,我没有发现可以使用php创建的进程数量有限制,只要它们在创建后不久就被杀死。我相信用户可以在 linux 中创建的进程是有限制的,可以使用ulimit.

于 2012-04-18T15:36:56.137 回答