Что делает этот код C? - PullRequest
       7

Что делает этот код C?

4 голосов
/ 17 сентября 2010

Я действительно новичок в программировании на C, хотя я занимался немало другими типами программирования.

Мне было интересно, может ли кто-нибудь объяснить мне, почему эта программа выдает 10.

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

int value = 10;

int main()
{
    pid_t pid;

    pid = fork();
    if(pid == 0){
    value += 10;
    }
    else if(pid > 0){
        wait(NULL);
        printf("parent: value = %d\n", value); //Line A
        exit(0);
    }
}

Я знаю, что вывод "parent: value = 10".Кто-нибудь знает почему?

Спасибо!

Ответы [ 6 ]

16 голосов
/ 17 сентября 2010

fork создает два процесса («родительский» и «дочерний»). Каждый процесс имеет разное значение pid в вашем примере. У дочернего процесса pid равен 0. У родительского процесса есть pid дочернего pid операционной системы (назначается операционной системой).

В вашем примере каждый процесс имеет свою собственную value в своей памяти. Они не совместно используют память (как вы думаете, они должны по вашему вопросу.) Если вы измените один процесс (первую часть if), это не будет отражено во втором процессе (вторая часть если.)

Редактировать: Объяснил значение pid.

4 голосов
/ 17 сентября 2010

О fork ():

  • Если fork () возвращает отрицательное значение, создание дочернего процесса завершилось неудачно.
  • Если fork () возвращает ноль ввновь созданный дочерний процесс.
  • Если fork () возвращает положительное значение, идентификатор процесса дочернего процесса, родительскому.

Так что в вашем случае он обязан вернутьчисло больше 0 и, следовательно, значение останется 10 & будет напечатано.

2 голосов
/ 17 сентября 2010

Ну, fork порождает новый процесс. Он более или менее копирует текущий процесс, и новый (дочерний) и старый (родительский) продолжаются в одной и той же точке кода. Но здесь есть одно существенное отличие (которое нас интересует): для дочернего элемента fork возвращает 0. Для родительского элемента возвращается идентификатор процесса дочернего элемента.

Так что часть if(pid ==0) верна для ребенка. Ребенок просто добавляет 10 к его value, а затем выходит, так как больше нет кода.

Часть else верна для родителя (за исключением очень редкого случая, когда fork вернул ошибку с -1). Родитель просто wait s для ребенка, чтобы выйти. Но потомок изменил свою собственную копию value, один из родителей все еще не тронут, и поэтому вы получаете вывод «10». Затем родитель также выходит.

0 голосов
/ 17 сентября 2010

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

Системный вызов fork возвращает идентификатор процесса вновь созданного процесса родительскому элементу и ноль дочернему, поэтому в этом коде дочерний элемент будет увеличивать свою собственную копию переменной значения, а родительский объект распечатывает свою собственную копию.

Вы часто будете видеть fork, за которым следует exec внутри дочернего элемента, чтобы он заменял себя другой программой.

0 голосов
/ 17 сентября 2010

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

Так что они оба должны работать одинаково.

НО, fork возвращает 0 в дочернем процессе и pid дочернего процесса в родительском процессе.

Это объясняет mojo позади if( pid==0 ) части.

Поэтому, когда дочерний процесс изменяет значение value, он фактически меняет его в своей собственной копии (помните: процесс скопирован, поэтому скопированы и разделы данных).

Тем временем родительский процесс выполняется со своим старым значением value, которое равно 10.

Даже после того, как ребенок изменил свою копию value и умер, копия родителя по-прежнему 10.

0 голосов
/ 17 сентября 2010

fork() создает новый процесс: он имеет два возвращаемых значения в двух разных контекстах, поэтому оба пути выполняются в вашем операторе if. Условное в основном используется для определения того, какой процесс вы запускаете после разветвления.

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