2010-09-16 16 views
4

Я действительно новичок в программировании на С, хотя я сделал довольно много других типов программирования.Что делает этот 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); 
    } 
} 

Я знаю выход «родитель: значение = 10». Кто-нибудь знает, почему?

Спасибо!

+0

СПАСИБО! Полностью понять, что происходит сейчас! – kralco626

+0

Это распространенный вопрос о домашнем задании на некоторых курсах программирования, его домашняя работа не так ли? – ldog

+0

Если вы удовлетворены ответом, то это хорошая привычка отмечать лучший ответ. Это вознаградит плакат, а также сообщит другим, что вопрос уже разрешен. –

ответ

4

О вилке():

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

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

+0

Удивительный ответ. Я пытаюсь обвести голову вокруг этого. Таким образом, родительский процесс получает число больше 0 и, следовательно, переходит в часть else и печатает. Дочерний процесс получает 0. Что делает этот дочерний процесс? Создает ли он новый процесс, который выполняется из текущей строки? или с самого начала кода? – kralco626

+0

@ kralco626 это копия родительского процесса, выполняемая из той же точки/состояния: http://man.cx/fork%282%29 – Bruno

16

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

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

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

+3

pid, возвращаемый fork, равен 0 для дочернего процесса и больше 0 для родительского процесса. –

+0

Почему PID для дочернего процесса 0? Почему родительский процесс не должен быть 0 и каждый дочерний приращение оттуда? – kralco626

+0

@ kralco626: 'man fork' говорит:« При успехе PID дочернего процесса возвращается в родительском, а 0 возвращается в дочернем ». – Bruno

0

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

+0

, но есть только одна выходная линия. Можете ли вы пройти меня через то, что происходит? Почему родительский и дочерний процесс не создают и не выводят оператор? – kralco626

+0

Потому что в дочернем случае fork возвращает 0. В родителе fork возвращает pid дочернего элемента. –

+0

haha ​​ya теперь я понимаю.Процесс переходит от точки вызова fork(). Дочерний процесс со значением 0 и родителем со значением, большим, чем 0. Я думаю, что понял! – kralco626

2

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

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

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

0

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

Таким образом, оба они должны выполняться одинаково.

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

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

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

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

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

0

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

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

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