Я нашел правильное объяснение этого вопроса on Geeks for Geeks:
Система вызова вилка() породит процессы, как листья растущего бинарного дерева , Если мы будем называть fork() два раза, это вызовет 22 = 4 процесса. Все эти 4 процесса образуют листовые дети двоичного дерева. В общем случае, если мы называем безусловный уровень l и fork(), мы будем иметь 2l процессов на уровне (l + 1). Это эквивалентно числу максимальных дочерних узлов в двоичном дереве на уровне (l + 1).
В качестве другого примера предположим, что мы вызываем вызов fork() 3 раза безоговорочно. Мы можем представить порожденный процесс, используя полное двоичное дерево с тремя уровнями. На уровне 3 мы будем иметь 23 = 8 дочерних узлов, что соответствует числу запущенных процессов.
Замечание о логических операторов C/C++:
Логический оператор & & имеет больше приоритет, чем ||, и слева направо ассоциативности. После выполнения левого операнда итоговый результат будет оценен, а выполнение правильного операнда зависит от результата левого операнда, а также от типа операции.
В случае И (& &) после оценки левого операнда правый операнд будет оцениваться только в том случае, если левый операнд оценивается в ненулевое значение. В случае OR (||) после оценки левого операнда правый операнд будет оцениваться только в том случае, если левый операнд будет равен нулю.
Возвращаемое значение вилки():
Людей страницы вилки() приводит следующий отрывок о возвращаемом значении,
«В случае успеха, PID дочернего процесса возвращаются в родителе, и 0 возвращается в дочернем элементе. При ошибке -1 возвращается родительскому, никакой дочерний процесс не создается, а errno устанавливается соответствующим образом. "
PID - это как дескриптор процесса и представлен как беззнаковый int. Мы можем заключить, что fork() вернет ненулевое значение в родительском и ноль в child. Проанализируем программу. Для простоты обозначений, маркировать каждую вилку(), как показано ниже,
#include <stdio.h>
int main()
{
fork(); /* A */
( fork() /* B */ &&
fork() /* C */) || /* B and C are grouped according to precedence */
fork(); /* D */
fork(); /* E */
printf("forked\n");
return 0;
}
Первые две вилки() вызовы называются безоговорочно.
На уровне 0 у нас есть только основной процесс. Основной (m на диаграмме) создаст дочерний C1, и оба будут продолжать выполнение. Дети пронумерованы в порядке возрастания своего творчества.
На уровне 1 мы выполняем операции m и C1 и готовы к выполнению fork() - B. (Обратите внимание, что B, C и D называются операндами & & и операторами ||). Начальное выражение B будет выполняться в каждом дочернем и родительском процессах, выполняющихся на этом уровне.
На уровне 2 из-за fork() - B, выполняемого m и C1, мы имеем m и C1 в качестве родителей, а C2 и C3 - как дети.
Возвращаемое значение fork() - B отличное от нуля в родительском и ноль в дочернем. Поскольку первый оператор равен & &, из-за нулевого значения возврата дети C2 и C3 не будут выполнять следующее выражение (fork() - C). Процессы родителей m и C1 будут продолжены с fork() - C. Дети C2 и C3 будут непосредственно выполнять fork() - D, чтобы оценить значение логической операции OR.
На уровне 3 мы имеем m, C1, C2, C3 в качестве запущенных процессов и C4, C5 в качестве детей. Теперь выражение упрощается до ((B & & C) || D), и в этот момент значение (B & & C) очевидно. У родителей это отличное от нуля, а у детей - ноль. Следовательно, родители знают об итогах общего В & & C || D, пропустит выполнение fork() - D. Так как у детей (B & & C), оцененных до нуля, они будут исполнять fork() - D. Следует отметить, что дети C2 и C3, созданные на уровне 2, будут также запускайте fork() - D, как указано выше.
На уровне 4 мы будем иметь m, C1, C2, C3, C4, C5 в качестве запущенных процессов и C6, C7, C8 и C9 в качестве дочерних процессов. Все эти процессы безоговорочно выполняют fork() - E и порождают одного ребенка.
На уровне 5 у нас будет 20 процессов. Программа (на Ubuntu Maverick, GCC 4.4.5) печатала «раздвоенную» 20 раз. Один раз родительский корень (основной) и отдых детьми. В целом будет создано 19 процессов.
Почему бы не начать, скомпилировав и запустив его, и посмотреть, сколько у вас «разветвленных» сообщений? –
Это домашнее задание? Ни один здравомыслящий человек не напишет 'fork() && fork() || вилка() '. Вы можете разделить эту строку и добавить больше отладочного вывода. – ThiefMaster
Я собрал его много раз, каждый раз, когда он получает другой ответ ... см. Здесь http://ideone.com/CXlkR –