Что происходит, когда процесс разветвлен?

Я читал о ветвлении и от того, что я понимаю, процесс клонирован, но которые обрабатывают? Сам сценарий или процесс, который запустил сценарий?

Например:

Я выполняю rTorrent на своей машине и когда поток завершается, мне выполняли сценарий против него. Этот сценарий выбирает данные из сети, таким образом, требуется несколько секунд для завершения. В это время мой процесс rtorrent замораживается. Таким образом, я сделал ветвление сценария с помощью следующего

my $pid = fork();
if ($pid == 0) { blah blah blah; exit 0; }

Если я запускаю этот скрипт от CLI, он возвращается к оболочке в течение секунды, в то время как он работает в фоновом режиме, точно как я предназначил. Однако, когда я выполняю его от rTorrent, это, кажется, еще медленнее, чем прежде. Таким образом, что точно было разветвлено? rtorrent обрабатывал, клонируют себя, и мой сценарий работал в этом, или мой сценарий клонировал себя? Я надеюсь, что это имеет смысл.

6
задан friedo 7 March 2010 в 02:14
поделиться

6 ответов

Чтобы ответить на номинальный вопрос, поскольку вы отметили, что принятый ответ не отвечает, fork влияет на процесс, в котором он вызывается. В вашем примере rTorrent порождает процесс Perl, который затем вызывает fork , это процесс Perl, который дублируется, поскольку это был процесс Perl, который вызвал fork .

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

2
ответ дан 8 December 2019 в 12:58
поделиться

Функция fork() возвращается ДВА раза! Один раз в родительском процессе, и один раз в дочернем процессе. В целом, оба процесса ИДЕНТИЧНЫ во всех отношениях, как если бы КАЖДЫЙ из них только что вернулся из fork(). Разница лишь в том, что в одном из них возвращаемое значение из fork() равно 0, а в другом оно ненулевое (PID дочернего процесса).

Таким образом, какой бы процесс ни выполнял ваш Perl-скрипт (если это встроенный интерпретатор Perl внутри rTorrent, то rTorrent будет этим процессом), он будет продублирован именно в тот момент, когда произойдет fork().

6
ответ дан 8 December 2019 в 12:58
поделиться

Я думаю, что нашел проблему, просмотрев исходники rTorrent. Для некоторых процессов он считывает весь вывод, отправленный в stdout, прежде чем продолжить работу. Если это происходит с вашим процессом, rTorrent будет блокироваться, пока вы не закроете процесс stdout. Поскольку вы используете форкинг, ваш дочерний процесс использует тот же stdout, что и родительский. Ваш родительский процесс завершится, но канал останется открытым (потому что ваш дочерний процесс все еще запущен). Если вы сделаете strace rTorrent, я готов поспорить, что он будет заблокирован на этом read() вызове во время выполнения вашей команды.

Попробуйте закрыть/перенаправить stdout в вашем perl-скрипте перед fork().

4
ответ дан 8 December 2019 в 12:58
поделиться

Весь процесс, содержащий интерпретатор, разветвляется. К счастью, память является копией при записи, поэтому нет необходимости копировать всю память процесса для разветвления. Однако такие вещи, как файловые дескрипторы, остаются открытыми. Это позволяет дочерним процессам обрабатывать их, но может вызвать проблемы, если они не закрыты должным образом. В общем, fork () не следует использовать во встроенном интерпретаторе, за исключением случаев крайнего принуждения.

3
ответ дан 8 December 2019 в 12:58
поделиться

Мой совет - "не делайте этого".

Если интерпретатор Perl встроен в процесс rtorrent, вы почти наверняка форкнули весь процесс rtorrent, последствия которого, вероятно, в лучшем случае плохо определены. Вообще, это плохая идея - играть с вещами на уровне процесса во встроенном интерпретаторе, независимо от языка.

Есть большая вероятность, что какая-то блокировка не освобождается должным образом, или что потоки внутри процессов идут непреднамеренными и, возможно, конкурирующими путями.

2
ответ дан 8 December 2019 в 12:58
поделиться

Когда мы создаем процесс с помощью fork, дочерний процесс будет иметь копию адресного пространства. Таким образом, дочерний процесс также может использовать адресное пространство. И это также может получить доступ к файлам, которые открываются родителем. Мы можем контролировать дочерний элемент. Чтобы получить полный статус дочернего элемента, мы можем использовать wait.

1
ответ дан 8 December 2019 в 12:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: