Я не понимаю этот пример fork () - PullRequest
14 голосов
/ 13 февраля 2012

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

#include <unistd.h>

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

Process graph

Ответы [ 7 ]

30 голосов
/ 13 февраля 2012

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

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

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

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

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

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

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

12 голосов
/ 13 февраля 2012

Если ваш основной процесс имеет 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, так как i == 1.

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

Подпроцесс B имеет i ==0, когда это начинается.Он порождает подпроцесс E и разрывается внутри цикла for.(я == 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();
}
6 голосов
/ 13 февраля 2012

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

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

Я могу сосчитать шесть процессов (X) здесь:

i=0          fork()
            /      \
i=1   fork()        fork()
      /    \>0       /   \>0
      |    X break   |   X break
i=2 fork()       fork()
     / \          /  \
    X  X         X    X
3 голосов
/ 13 февраля 2012

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

i = 0

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

i = 1

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

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

i = 2

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

3 голосов
/ 13 февраля 2012

цикл запускается с i==0 до i==2.

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

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

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

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

2 голосов
/ 13 февраля 2012

В дочерних процессах цикл продолжает повторяться. Так что они тоже производят новые процессы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...