Запутался с fork () - PullRequest
       6

Запутался с fork ()

4 голосов
/ 03 октября 2011

Мне трудно понять, что делает команда fork () при разных сценариях. Вот пример кода из моей книги:

int main() {
    int a = 12;
    int b = 9;
    int fid = fork();

    if (fid == 0) {
        a++;
    }
    else {
        wait(NULL);
        b = b - 5;
    }

    printf("program exit. a = %d, b = %d\n", a, b);
    return 0;
}

Может ли кто-нибудь рассказать мне, что делает команда fork () в этом случае, и, возможно, привести еще несколько примеров для пояснения?

Ответы [ 4 ]

12 голосов
/ 03 октября 2011
                 [main]
                 a = 12
                 b = 9

                 fork()
                   |
                   |
    +--------------+--------------+
    |                             |  
    |                             |
[parent]                       [child]

fid = 1234                     fid = 0
wait(NULL)                     a++
   ...                         printf("a = 13, b = 9");
   ...                         return 0
   ...                         <exit>
b = b - 5
printf("a = 12, b = 4");
return 0
<exit>

После выполнения fork() существует две копии программы. Каждый процесс получает свои собственные копии переменных, поэтому теперь есть два a, два b и т. Д. Единственное различие между двумя программами - это значение, возвращаемое из fork(): в дочернем процессе fork() возвращает 0; в родительском процессе он возвращает PID дочернего элемента.

Дочерний процесс увеличивает a, печатает значения a и b и выходит.

Родительский процесс сначала ожидает завершения дочернего процесса. Только после того, как ребенок закончил, он продолжает, вычитая 5 из b, распечатывая a и b, и затем выходя.

wait(NULL) гарантирует, что распечатка дочернего процесса всегда идет раньше, чем распечатка родителя, поэтому вы всегда будете получать одинаковые выходные данные в надежном порядке. Без этого вы не сможете зависеть от порядка двух распечаток. Это будут те же сообщения, но в непредсказуемом порядке.

4 голосов
/ 03 октября 2011
  1. a установлено на 12, b установлено на 9.

  2. fork вызвано, теперь у нас есть два процесса.

  3. Родитель получает PID дочернего элемента и переходит к предложению else.Ребенок получает 0 и переходит к предложению if.

  4. Родитель ожидает завершения работы ребенка.

  5. Дочерние приращенияего копия a.Таким образом, a теперь 13 у ребенка и 12 у родителя.

  6. Ребенок выходит, выводя 13 и 9.

  7. Родитель вычитает 5 из своей копии b, поэтому b теперь равен 4 в родительском.

  8. Родитель завершает работу, выводя 12 и 4.

Обратите внимание, что точный порядок выполнения дочернего элемента и родительского элемента после fork не гарантируется, но это не меняет результаты, поскольку родительский элемент ожидает завершения дочернего процесса.прежде чем он что-то сделает.

Кроме того, обратите внимание, что обычно завершение обоих процессов является плохой практикой.Когда один процесс завершается нормально, он запускает обработчики очистки, которые могут запутать другой процесс, например, путем изменения позиции файла в описаниях общих файлов, что приводит к повреждению данных.

3 голосов
/ 03 октября 2011

Когда вы вызываете fork(), весь процесс, включая всю память / переменные и т. Д., Дублируется.

Поэтому после вызова fork каждый процесс имеет свою собственную копию ab, которые начинаются как 12 и 9 соответственно.

Процесс 0 будет увеличивать свою собственную копию a.Процесс 1 уменьшит (на 5) свою собственную копию b.

, поэтому они должны вывести:

Process 0: a = 13, b = 9
Process 1: a = 12, b = 4
0 голосов
/ 04 октября 2011

Его о / п будет Родитель :: а = 12, б = 4 Ребенок :: а = 13, б = 9

, поскольку оба процесса выполняются одновременно, но оба имеют разные копии локальных переменных a, b так местный вар. затронутый одним процессом не будет виден другому процессу, так как оба работают над своими собственными копиями

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