fork () используется как для условия цикла генерирует состояние гонки? - PullRequest
1 голос
/ 19 ноября 2011

хорошо, вот пример, который мы провели на сегодняшнем экзамене по операционным системам

, учитывая эту программу на C

#include <unistd.h>
#include <stdlib.h>

int  main(){
    int i;
    for(i=2;i>=1&&!fork();i--)
            printf("%d\n",i);

exit(EXIT_SUCCESS);
}

, выполняя ее, выдает следующее:

2
1

То, что я нашел неоднозначным, - это то, как программа управляет индексом «i» и каков будет правильный порядок выполнения процессов (если есть порядок или это случайный порядок, установленный планировщиком?)

И почему напечатаны только 2 и 1 - Мои предположения:

(father executes the "for" only for i=2, prints 2 then exits ?)
(the first child starts from i=1 forks a child prints 1 exits ?)

На данный момент мой вопрос:

Есть ли второй разветвленный ребенок, который не 'введите для?а 2 напечатаны отцом, а 1 - первым ребенком?

И еще одна заключительная вещь:

Как бы вы переписали эту вилку, чтобы сделать ее более читабельной (например, если if-statement)

Ответы [ 2 ]

2 голосов
/ 19 ноября 2011

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

Итак, что происходит с i, так это то, что у него будет точно такое же значение в дочернем элементе, какое у родительского элемента во время разветвления.

Итак, когда i равно 2:

for parent: i>=1 && !fork()  <-- fails
for child1: i>=1 && !fork()  <-- succeeds

Итак, дочерний элемент исходной программы печатает 2.

Теперь родительский объект завершен, а дочерний элемент 1 запущен.Он выполняет i--, и теперь i равен 1:

for child1:   i>=1 && !fork()  <-- fails
for child1.1: i>=1 && !fork()  <-- succeeds

Итак, снова child1 завершает работу и его дочерний элемент child1.1 отправляется в for и печатает 1. Затем он выполняет i-- и i становится 0, что не удается i>=1 и из-за оценка короткого замыкания , fork не выполняется.Этот child1.1 также завершается.

Чтобы ответить на ваш последний вопрос, обычно так пишется fork:

pid_t pid = fork();
if (pid)
{
    // in parent
}
else
{
    // in child
}

Теперь все, что вам нужно, это цикл for:

#include <unistd.h>
#include <stdlib.h>

int  main(){
    int i;
    for(i=2;i>=1;i--)
        if (fork())
            break;              /* parent wants to break */
        else
            printf("%d\n",i);   /* child prints something */

    exit(EXIT_SUCCESS);
}
2 голосов
/ 19 ноября 2011

Цикл for() проверяет условие перед каждой итерацией цикла, включая первую.Это означает, что исходный родительский процесс начинается с i = 2 и оценивается i >= 1 && !fork().fork() возвращает ненулевой PID для родителя и ноль для дочернего, поэтому !fork() имеет значение false в родительском элементе, и цикл не выполняется: родительский объект завершается.

В первом дочернем элементе, !fork() имеет значение true, поэтому цикл выполняется.Он печатает 2, затем уменьшается i.Теперь он выполняет i >= 1 && !fork() - снова, !fork() ложно в первом дочернем элементе, поэтому он выходит из цикла for и программы.

Во втором дочернем элементе (дочернем элементе первого дочернего элемента), !fork()возвращает true, поэтому цикл выполняется.Он печатает 1, затем уменьшается i.Теперь он оценивает i >= 1 && !fork().Поскольку i >= 1 становится ложным, fork() никогда не вызывается;он выходит из цикла и программы.В этот момент все процессы завершились.

Вы можете переписать цикл for() как цикл while() и сделать оценку короткого замыкания && явной:

int  main()
{
    int i;

    i = 2;
    while (i >= 1) {
        if (fork() != 0)
            break;

        printf("%d\n", i);
        i--;
    }

    exit(EXIT_SUCCESS);
}
...