Я не понимаю этот пример fork()

У меня есть этот пример кода, но я не понимаю, почему этот код создает 5 процессов плюс оригинал. (Всего 6 процессов)

#include <unistd.h>

int main(void) {
    int i;
    for (i = 0; i < 3; i++) {
        if (fork() && (i == 1)) {
            break;
        }
    }
}

Process graph

Ответы

Ответ 1

fork() разбивает процесс на две части и возвращает либо 0 (если этот процесс является дочерним), либо PID дочернего элемента (если этот процесс является родительским). Итак, эта строка:

if (fork() && (i == 1)) break;

Говорит "если это родительский процесс, и это второй раз через цикл, вырваться из цикла". Это означает, что цикл работает следующим образом:

  • i == 0: первый раз через цикл, i равен 0, мы создаем два процесса, которые входят в цикл в i == 1. Всего сейчас два процесса

  • i == 1: оба этих процесса fork, но два из них не продолжают выполнять итерацию из-за строки if (fork() && (i == 1)) break; (две из них не продолжаются, это оба родителя в вызовах fork), Всего четыре процесса,, но только два из них продолжают цикл.

  • i == 2: Теперь два, которые продолжают цикл как fork, , приводящие к 6 процессам.

  • i == 3: все 6 процессов выходят из цикла (поскольку i < 3 == false, больше нет циклов)

Ответ 2

Если ваш основной процесс имеет pid A, а B - F - подпроцессы pids, то:

A    spawns  B          i=0
A    spawns  C          i=1
C    run from 'fork'    i=1
C    spawns  D          i=2
B    run from 'fork'    i=0
B    spawns  E          i=1
D    run from 'fork'    i=2
E    run from 'fork'    i=1
E    spawns  F          i=2
F    run from 'fork'    i=2

Где i - значение i контекста процесса (под). Поскольку fork создает точную копию текущего процесса, переменная i также будет скопирована. Когда A порождает B, i равно 0. Когда A порождает C, i равно 1. Процесс A теперь выходит из цикла for, поскольку я == 1.

Теперь подпроцесс C начинает запускаться с i == 1. Обратите внимание, что он не будет ломаться внутри цикла for, поскольку fork(), в точке нереста C, возвращает 0. Вместо этого он будет зацикливаться, увеличивая i до 2, порождать D и выйти из-за условия for-loop.

Подпроцесс B имеет i == 0, когда он запускается. Он порождает подпроцесс E и разбивается внутри цикла for. (i == 1)

И так далее...

Когда вы пытаетесь найти такие вещи, я могу дать вам совет:

Сделайте промежуточные переменные и распечатайте их.

Я изменил ваш код, чтобы он распечатывал только что описанные мной вещи:

#include <unistd.h>
#include <stdio.h>

int main(void) {
    int i;
    for (i= 0; i < 3; ++i) {
        int f = fork();
        printf("%i\tspawns\t%i\ti=%i\n", getpid(), f, i);
        if (f && (i == 1))
            break;
    }

    getchar();
}

Ответ 3

В родительском процессе fork() возвращает PID дочернего процесса, а в дочернем процессе он возвращает 0. Учитывая это, посмотрите на каждую итерацию цикла for: (Скажем, для простоты, что PID исходного процесса равен 1)

  • я == 0
    • Процесс 1: я == 0, fork возвращает PID дочернего процесса (скажем 2) (2!= 0), true && & false == false, поэтому мы не сломаемся.
    • Процесс 2: я = 0, fork возвращает 0, false && false == false, поэтому мы не сломаемся.
  • я == 1
    • Процесс 1: я == 1, fork возвращает PID дочернего процесса (скажем 3), true && & true == true, поэтому перерыв.
    • Процесс 2: я == 1, fork возвращает PID дочернего процесса (скажем 4), true && & true == true, поэтому перерыв.
    • Процесс 3: я == 1, fork возвращает 0, false && & true == false, поэтому не прерывайте.
    • Процесс 4: я == 1, fork возвращает 0, false && true == false, поэтому не прерывайте.
  • я == 2
    • Процесс 1 вышел из цикла.
    • Процесс 2 вышел из цикла.
    • Процесс 3: я == 2, fork возвращает PID дочернего процесса (скажем, 5), true && & false == false, поэтому не прерывайте
    • Процесс 4: я == 2, fork возвращает PID дочернего процесса (скажем, 6), true && & false == false, поэтому не прерывайте
    • Процесс 5: я == 2, fork возвращает 0, false && false == false, поэтому не прерывайте
    • Процесс 6: я == 2, fork возвращает 0, false && false == false, поэтому не прерывайте
  • я == 3 так сделано с помощью цикла.

Ответ 4

Здесь можно считать шесть процессов (X):

i=0          fork()
            /      \
i=1   fork()        fork()
      /    \>0       /   \>0
      |    X break   |   X break
i=2 fork()       fork()
     / \          /  \
    X  X         X    X

Ответ 5

цикл выполняется от i==0 до i==2.

В первом итерации исходный процесс (p0) создает еще один (p1)

Во второй итерации p0 и p1 создайте один новый процесс каждый (p2 и p3) и break (Так как i==1 и fork возвращают отцу ненулевое значение).

В третьем итерации p2 и p3 создайте каждый новый процесс (p4 и p5).

Итак, наконец, у вас появилось 5 новых процессов.

Ответ 6

Сначала у нас есть один процесс. Рассмотрим итерации цикла:

i = 0

Первый процесс вызывает fork. Теперь у нас есть 2 процесса.

i = 1

Два процесса вызывают fork. Теперь мы имеем 4.

Fork возвращает 0 во вновь созданных процессах: два процесса прерываются от цикла, а два будут продолжаться в цикле.

i = 2

Два оставшихся процесса вызывает fork. Мы получаем 2 новых процесса (всего 6).

Ответ 7

В процессах детей цикл продолжает повторяться. Поэтому они также производят новые процессы.