Понимание вилки в C - PullRequest
1 голос
/ 11 ноября 2010

У меня возникли проблемы с пониманием следующего простого кода C:

int main(int argc, char *argv[]) {
    int n=0;
    fork();
    n++;
    printf("hello: %d\n", n);
}

Мое текущее понимание fork состоит в том, что начиная с этой строки кода он будет разбивать оставшуюся часть кода на 2, которая будет выполняться параллельно до тех пор, пока «не будет больше кода» для выполнения.

Из этой призмы код после разветвления будет:

а)

    n++;                       //sets n = 1
    printf("hello: %d\n", n);  //prints "hello: 1"

б)

    n++;                       //sets n = 2
    printf("hello: %d\n", n);  //prints "hello: 2"

Что происходит, однако, это то, что оба печати

hello: 1

Почему это?

РЕДАКТИРОВАТЬ: Только теперь мне стало ясно, что в отличие от потоков, процессы не разделяют одну и ту же память. Это правильно? Если да, то это будет причиной.

Ответы [ 7 ]

7 голосов
/ 11 ноября 2010

После fork () у вас есть два процесса, каждый со своей переменной n.

3 голосов
/ 11 ноября 2010

fork() запускает новый процесс, не разделяя переменные / ячейки памяти. Это очень похоже на то, что происходит, если вы выполняете ./yourprogram дважды в оболочке, предполагая, что первое, что делает программа - это разветвление.

2 голосов
/ 11 ноября 2010

В конце вызова fork () оба процесса могут ссылаться на одну и ту же копию n. Но при n ++ каждый получает свою копию с n = 0. В конце n ++; n становится 1 в обоих процессах. Оператор printf выводит это значение.

1 голос
/ 11 ноября 2010

проверьте этот код, и все должно быть понятнее (см. Справочные страницы, если вы не знаете, что делает определенная функция):

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

int count = 1;

int main(int argc, char *argv[]) {

    // set the "startvalue" to create the random numbers
    srand(time(NULL));
    int pid;

    // as long as count is <= 50
    for (count; count<=50; count++) {

        // create new proccess if count == 9
        if (count==9) {
            pid = fork();
            // reset start value for generating the random numbers
            srand(time(NULL)+pid);
        }

        if (count<=25) {
            // sleep for 300 ms
            usleep(3*100000);
        } else {
            // create a random number between 1 and 5
            int r = ( rand() % 5 ) + 1;
            // sleep for r ms
            usleep(r*100000);
        }

        if (pid==0) {
            printf("Child:  count:%d    pid:%d\n", count, pid);
        } else if (pid>0) {
            printf("Father: count:%d    pid:%d\n", count, pid);
        }
    }


    return 0;
}

счастливое кодирование; -)

1 голос
/ 11 ноября 2010

Системный вызов разветвляется больше, чем поток выполнения: также разветвлено пространство данных.В этот момент у вас есть две n переменные.

Из всего этого следует несколько интересных вещей:

  • Программа, которая должна выполнять fork ()рассмотрим неписанные выходные буферы.Их можно очистить перед разветвлением или очистить после разветвления, или программа может _exit () вместо exit (), чтобы, по крайней мере, избежать автоматической очистки буфера при выходе.
  • Fork часто реализуется с помощью copy-on-write , чтобы избежать ненужного дублирования большой памяти данных, которая не будет использоваться в дочернем элементе.
  • Наконец,альтернативный вызов vfork () был восстановлен в большинстве текущих версий Unix после исчезновения в течение некоторого времени после его появления в 4.0BSD.Vfork () не претендует на дублирование пространства данных, поэтому реализация может быть даже быстрее, чем fork-on-write fork ().(Его реализация в Linux может быть вызвана не столько соображениями скорости, сколько тем, что несколько программ фактически зависят от семантики vfork ().)
1 голос
/ 11 ноября 2010

Вы действительно ответили на свой вопрос в своем редактировании.

1 голос
/ 11 ноября 2010

На самом деле вы породили новый процесс той же программы.Это не закрывающая вещь.Вы можете использовать каналы для обмена данными между родителем и ребенком.

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