pcntl_fork и затем pcntl_exec или pcntl_exec, а затем pcntl_fork - PullRequest
2 голосов
/ 22 октября 2010

Объяснение: Часть создаваемого мною приложения требует проверки тысяч записей и своевременного выполнения действий с ними .Поэтому для каждой записи я хочу создать новый процесс.Тем не менее, мне нужно соединение с БД, чтобы сделать еще одну проверку этой записи.Насколько я понимаю, ребенок наследует соединение с БД.Поэтому последующие вилки имеют ошибки БД.

Я думал, что смогу pcntl_exec ('php /path/script.php');и затем pcntl_fork, чтобы вызывающий процесс не задерживался.

Или я могу pcntl_fork, а затем pcntl_exec в дочернем процессе.Или, может быть, я должен использовать exec () вместо pcntl_exec ().

Мой вопрос: Есть ли какие-либо недостатки или преимущества в любом заказе?

Примечания: Может быть, я представляю эту проблему, так как думал, что вызывающий процесс php будет ждать возвращения pcntl_exec.Но это не то, что указано в документации:

Возвращает FALSE в случае ошибки и не возвращает в случае успеха.

Как функция может возвращать значение иногда, а иногда нет?Это звучит как плохо написанные документы.

Состояние комментариев Фахадсада:

Как только выполненный процесс заканчивается, управление возвращается к процессу веб-сервера.

Если этов таком случае, тогда мне нужно раскошелиться.

Редактировать: код для смущенного - включая меня;)

<?php

class Process
{

    public function __construct($arg = false)
    {
        if ($arg == "child")
        {
            $this->act();
        }
        else
        {
            $this->run();
        }
    }

    public function run()
    {
        echo "parent before fork:", getmypid(), PHP_EOL;
        $pid = @ pcntl_fork();
        echo $pid, PHP_EOL;

        if ($pid == -1)
        {
            throw new Exception(self::COULD_NOT_FORK);
        }
        if ($pid)
        {
        // parent
            echo "parent after fork:", getmypid(), PHP_EOL;
        }
        elseif ($pid == 0)
        {
        // child
            echo "child after fork:", getmypid(), PHP_EOL;
            //echo exec('php Process.php child');
            echo pcntl_exec('/usr/bin/php', array('Process.php', 'child'));
        }
        return 0;
    }

    private function act()
    {
        sleep(1);
        echo "forked child new process:", getmypid(), PHP_EOL;
        return 0;
    }
}

$proc = new Process($argv[1]);

Если вы раскомментируете exec и комментируетеpcntl_exec, вы увидите, что pcntl_exec заменяет процесс.Что, я думаю, экономит некоторые ресурсы.

Ответы [ 3 ]

1 голос
/ 22 октября 2010

Это действительно сбивает с толку - вы пытаетесь применить очень сложные методы - но вы применяете их совершенно неправильно.

fork создает новую рабочую копию текущего процесса.Exec запускает новый процесс.Вы не будете использовать их обоих для запуска одного процесса.

Но прежде чем я подробно расскажу, как правильно использовать fork и exec, я должен отметить, что они не являются подходящими инструментами для решения этой проблемы..

По возможности следует избегать пакетной обработки.Данные обычно поступают с конечной скоростью (хотя скорость может быть стохастической) - обычно правильный подход, позволяющий избежать пакетной обработки, состоит в том, чтобы обрабатывать запросы синхронно или с помощью очередей.Там, где пакетная обработка неизбежна, параллелизация и / или конвейерная обработка обычно улучшают пропускную способность.Несмотря на то, что существует множество сложных методов для достижения этого (например, сокращение карты), просто адекватного разделения данных обычно достаточно.В то время как ваша основная идея сводится к разбиению на отдельные части, это:

1) будет менее эффективным, чем работа с небольшими партиями

2) очень затруднит ограничение потребления ресурсов системой (Что, если вы породите 500 процессов и ваша СУБД поддерживает только 200 одновременных подключений?)

Если вы не можете работать с обработкой синхронно, а запуск очереди с несколькими подписчиками нецелесообразен, я бы предложил просто разделитьданные в (ограниченное количество) меньшие партии и процессы нереста, чтобы справиться с ними.Обратите внимание, что popen (), proc_open () и pcntl_fork () не блокируются на время выполнения порожденного процесса.(подсказка - используйте оператор модуля )

Если вы хотите запустить обработку по HTTP-запросу (или у вас есть другая причина для запуска их в отдельных группах сеансов), тогда попросите Google для'PHP долго запускает процессы setsid).

0 голосов
/ 05 августа 2011

Теперь, когда определены fork и exec, fork не будет делать то, что вы хотите.Он скопирует ВСЕ из текущей среды сценариев в новое пространство, включая дескриптор файла указатели .Да, это правильно - дети используют те же файловые дескрипторы, что и родители.

Представьте себе хаос при использовании расширения mysql, которое поддерживает свои собственные файловые дескрипторы; -)

0 голосов
/ 22 октября 2010

Это не имеет смысла. После выполнения exec () вы запускаете другой код, поэтому не может fork () впоследствии. Не возвращается при успехе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...