Вывод вызовов fork()

Каким будет результат следующих вызовов fork()?

func(){
fork();
fork();
fork() && fork() || fork();
fork();
print("Saikacollection\n");
}

Может ли кто-нибудь помочь мне получить ответ на этот код, а также некоторые пояснения, поскольку я новичок в ОС? Я нашел несколько вопросов о fork() на SO, но не смог многого понять.


person Prashant Singh    schedule 14.10.2012    source источник
comment
Однажды я сделаю ОС, которая выводит «Остановите безумие!» и умирает, когда происходит 4 ветвления без обработки между ними.   -  person cHao    schedule 14.10.2012
comment
Это не практический пример, просто вопрос интервью, чтобы проверить понимание   -  person Prashant Singh    schedule 14.10.2012
comment
Результатом является множество процессов.   -  person nneonneo    schedule 14.10.2012
comment
@nneonneo Не могли бы вы уточнить? как это произойдет?   -  person Prashant Singh    schedule 14.10.2012
comment
@cHao: OS X в этом отношении преуспевает; forkbombs обычно встречаются с временно недоступным ресурсом.   -  person nneonneo    schedule 14.10.2012
comment
@PrashantSingh: каждый fork() превращает один процесс в два. Затем оба снова будут fork(), и теперь у вас будет 4. Затем снова, и у вас будет 8. Половина этих (родительских процессов) снова разветвится, и теперь у вас есть 12. И т. д.   -  person cHao    schedule 14.10.2012
comment
@PrashantSingh: я шучу. В результате генерируется довольно большое количество процессов, поэтому вы, вероятно, увидите, что Saikacollection распечатывается множество раз. Я действительно не вижу смысла пытаться подсчитать, сколько их, и это довольно дерьмовый вопрос для интервью.   -  person nneonneo    schedule 14.10.2012
comment
@cHao посмотри, наконец, ответ, который я получил.   -  person Prashant Singh    schedule 03.11.2012
comment
@nneonneo Посмотрите ответ, который я опубликовал   -  person Prashant Singh    schedule 03.11.2012
comment
Форк бомбовый рейд! иди в бомбоубежище!   -  person Linuxios    schedule 03.11.2012


Ответы (3)


Коллекция Saika будет напечатана 40 раз в качестве вывода кода. Это можно объяснить следующим образом: -

Чтобы понять вывод, нам нужно знать следующее: -

  • При успешном выполнении вызова fork() создается новый дочерний элемент. Процесс создания дочернего элемента называется parent process.
  • Вызов fork() возвращает pid (идентификатор процесса) дочернего элемента родительскому
  • Fork() возвращает 0 дочернему процессу.

введите здесь описание изображения

Рассмотрим показанное изображение: -

Соглашение: все родительские (вызывающие) процессы записываются в left и помечаются star.

fork()
  • Вначале у нас есть только 1 процесс, поэтому вызов fork() создает дочерний процесс. Рассматривая корень дерева как уровень 1, мы видим, что на уровне 2 у нас есть два процесса: родительский (левый) и дочерний (правый).

    fork()

  • fork() снова создает 4 таких процессов, помеченных как 1, 2, 3, 4. Поскольку все четыре процесса далее будут проходить через аналогичную структуру кода, мы можем сказать, что общее количество процессов будет 4 раз, когда один процесс производит

    fork()&&fork()||fork()

  • Понимание этого утверждения предполагает осознание того факта, что в C && operator has more precedence than ||

  • Кроме того, если first из двух операндов, соединенных &&, становится wrong, мы don't check the second. Точно так же, если first из двух операндов || равен true, we don't check the second операнд.
  • Учтите, что вызов fork() на 1 (отмеченном) узле создает два процесса. В то время как родитель получает положительное число (pid) в качестве возврата, дочерний элемент получает 0. Итак, родитель выполняет второй оператор, а дочерний элемент переходит к fork() после || как отмечено на рисунке.
  • Выполнение &&fork() для родителя на 4-м уровне возвращает pid для одного процесса, который завершается, в то время как дочерний процесс этого шага получает 0. Таким образом, выполняется выполнение ||fork()
  • окончательный вызов ||fork() для дочернего элемента уровня 5, далее производит процесс в результате
  • Итак, в конце шага у нас есть 5 листьев (процессов), отмеченных на рисунке подчеркиванием.
  • Если бы мы сделали то же самое для всех трех узлов, мы могли бы получить 5*4 = 20 процессов.

    fork()

  • Final fork() всего лишь doubles количества процессов, доступных на этом шаге.

  • Итак, общее количество процессов = 2*20 = 40.
person Prashant Singh    schedule 03.11.2012

Saikacollection печатается 32 раза каждый раз с новой строки.

person Sahil Sharma    schedule 15.10.2012
comment
Предполагая, что ОС синхронизирует доступ к стандартному выводу между процессами. Если это не так, вы, вероятно, можете получить SSSSSSSSSSaaaaSaaaaaiSaaaaiiSSS... - person cHao; 15.10.2012
comment
Можете ли вы объяснить это немного, пожалуйста? - person Prashant Singh; 22.10.2012
comment
@user1747039 user1747039 Разве не должно быть 40 вместо 32. Я думаю, вы где-то ошиблись - person Prashant Singh; 02.11.2012

Если вы хотите, чтобы новый процесс был более независимым, вы можете взглянуть на семейство функций exec-* (POSIX) — так вы можете разветвить, а затем сразу заменить процесс форка (вы можете сделать это, так как новый разветвленный процесс контролируется тобой); Или, возможно, взгляните на popen().

person user6856855    schedule 21.09.2016