Дочерний объект, полученный в результате второго fork()
, знает о результатах первого fork()
, поскольку это точная копия родительского процесса.
Вы можете понять, что происходит, нарисовав для себя маленькое дерево. Начните с первого форка:
fork()
/\
/ \
parent --/ \-- child1
Родитель возвращает PID процесса child1
, а child1
возвращает 0. Итак, у нас есть что-то вроде:
PID(child1) && fork() || fork()
в родителе и:
0 && fork() || fork()
у ребенка. Короткое замыкание означает, что середина fork()
исходного выражения не выполняется в дочернем элементе, а только в родительском. Итак, что теперь происходит с деревом?
fork()
/\
/ \
parent --/ \-- child1
fork()
/\
/ \
parent --/ \-- child2
parent
является исходным процессом и получает PID child2
. child2
, как и child1
, получает 0. Как выглядят наши выражения сейчас?
parent: PID(child1) && PID(child2) || fork() = 1 || fork()
child: 0 || fork()
child2: PID(child1) && 0 || fork() = 0 || fork()
Теперь, снова с помощью короткого замыкания, parent
завершено и не выполняет последнее fork()
. Однако child
и child2
должны. Это оставляет нас со следующим деревом:
fork()
/\
/ \
parent --/ \-- child1
fork() fork()
/\ /\
/ \ / \
/ \ child1 --/ \-- child1-1
/ \
/ \
parent --/ \-- child2
fork()
/\
/ \
child2 --/ \-- child2-1
И это все. child1
и child2
каждый получает PID своих соответствующих дочерних элементов, а child1-1
и child2-1
каждый возвращает 0. 0. Подставляя эти значения в, окончательные выражения будут:
parent: 1
child1: 0 || PID(child1-1) = 1
child2: 0 || PID(child2-1) = 1
child1-1: 0 || 0 = 0
child2-1: 0 || 0 = 0
И это все - они все уходят.