Вызов fork()
не создает пару новых процессов (родительский, дочерний), но оставляет исходный процесс (родительский) и создает один другой процесс (дочерний), поэтому он "возвращается дважды".
В вашем первом фрагменте у вас действительно есть только один родитель. Единственная проблема, она заканчивается на самой первой итерации. :)
Посмотрите: i = 0
, теперь у нас есть только родительский процесс (назовите его P
).
P
вводит fork()
и оставляет его дважды: в P
(возвращая PID дочернего элемента) и во вновь созданном дочернем элементе C0
(возвращая 0). Тогда, согласно утверждению if
, C0
выводит 0
, P
ничего не делает. Тогда пути выполнения сходятся, и оба P
и C0
выходят. Теперь у нас нет наших процессов вообще.
Тело цикла второго фрагмента можно переписать следующим образом:
p = fork();
if (p == 0) {
print(i);
}
if (p > 0) {
exit(0);
}
Предположим, fork()
не вернет отрицательное число (ошибка), эти два тела if
на самом деле похожи на ветви then
- else
. Они заставляют дочерний процесс печатать его номер и старый родительский процесс, чтобы выйти, так что вы получаете поток процессов, заменяющих друг друга в последовательности (большинство из них действуют ровно один раз как дочерний, а затем как родительский).
Вам просто нужно переписать его так:
for(i = 0; i < 10; i++) {
p = fork();
if (p == 0) {
print(i);
exit(0);
}
// In fact, you should place waitpid(...) somewhere here,
// otherwise the child will become a so called zombie process
// after its termination.
// Only after parent termination they all will be
// finally recycled by init (PID 1) generally using up your system's
// resources for indefinite time
}
Теперь у вас есть P
, который создает C0
. C0
печатает его номер и сразу же выходит, в то время как P
просто переходит к следующей итерации цикла, создавая C1
, который так же, как C0
печатает его номер и выходит, и так далее. AFAIK это то, что изначально просили.
Обратите внимание, что в реальной жизни вам придется каким-то образом обрабатывать возвращаемое значение -1
, которое указывает на некоторую ошибку в вызове fork()
(так что на самом деле во втором переписанном мной фрагменте есть вероятность, что ни if
оператор выполнится), я их опускаю для простоты.