2013-04-05 3 views
3

Я совершенно не знаком с C и не узнал о процессах. Я немного запутался относительно того, что на самом деле делает код ниже, он взят из Википедии, но я видел это в нескольких книгах и не уверен, почему, например, мы делаем pid_t pid;, затем pid = fork();. Мое чтение, похоже, подсказывает, что дочерний процесс возвращает pid0, однако я думал, что исходный родительский процесс будет поддерживать pid0, увидев дерево с корнем как pid 0.Создание детского процесса через fork() в C

Что, например, pid = fork(); сделать родителям? Как это не делает то же самое для ребенка? И не pid = fork(); положить его в цикл, как он будет делать это для каждого ребенка?

В принципе, может кто-нибудь объяснить каждый шаг мне, как если бы я был, скажем, пять? Может быть, моложе? Благодаря!

#include <stdio.h> /* printf, stderr, fprintf */ 
#include <sys/types.h> /* pid_t */ 
#include <unistd.h> /* _exit, fork */ 
#include <stdlib.h> /* exit */ 
#include <errno.h> /* errno */ 

int main(void) 
{ 
    pid_t pid; 

    /* Output from both the child and the parent process 
    * will be written to the standard output, 
    * as they both run at the same time. 
    */ 
    pid = fork(); 

    if (pid == -1) 
    { 
     /* Error: 
     * When fork() returns -1, an error happened 
     * (for example, number of processes reached the limit). 
     */ 
     fprintf(stderr, "can't fork, error %d\n", errno); 
     exit(EXIT_FAILURE); 
    } 
    else if (pid == 0) 
    { 
     /* Child process: 
     * When fork() returns 0, we are in 
     * the child process. 
     */ 
     int j; 
     for (j = 0; j < 10; j++) 
     { 
     printf("child: %d\n", j); 
     sleep(1); 
     } 
     _exit(0); /* Note that we do not use exit() */ 
    } 
    else 
    { 
     /* When fork() returns a positive number, we are in the parent process 
     * (the fork return value is the PID of the newly created child process) 
     * Again we count up to ten. 
     */ 
     int i; 
     for (i = 0; i < 10; i++) 
     { 
     printf("parent: %d\n", i); 
     sleep(1); 
     } 
     exit(0); 
    } 
    return 0; 
} 
+1

В системах POSIX _very first_ обрабатывает это 'init' и всегда имеет идентификатор процесса 1. Нет процесса, когда-либо имевшего идентификатор процесса 0. –

+0

@JoachimPileborg Если это так, то почему значение pid дочернего элемента процесс, согласно, что я прочитал ноль? Разве это не должно быть больше, чем родитель? – mino

+2

@mino: * point * of 'fork()' return 0 - сделать тривиальным для обнаружения «aha, я у ребенка», так как вы обычно хотите сделать что-то другое в этом случае (и ваш собственный PID редко интересно, и его можно быстро найти с помощью 'getpid()' в любом случае). – unwind

ответ

2

После успешного завершения, fork() (source):

  • возвращает 0 к процессу
  • ребенка и возвращает идентификатор процесса дочернего процесса родительскому процессу.

Пример, который вы дали, хорошо объяснен. Тем не менее, я хотел бы уточнить, что оба процесса (родительский и дочерний) будут продолжать выполняться из функции fork().

Если вы хотите узнать ПИД ребенка (из кода ребенка), используйте getpidAPI.

+0

Зачем вам нужно использовать getpid f, он вернет pid дочернего процесса в родительский процесс? – mino

+1

Родительский процесс получит дочерний PID в качестве возврата функции 'fork()'. Если ребенок хочет получить свой собственный PID, вы должны использовать вызов getpid(). – Bechir

+0

Я понимаю, спасибо. – mino

1

fork это функция, которая возвращает дважды - один раз для родителей, когда-то для ребенка.

Для ребенка он возвращает 0, для родителя - pid ребенка, любое положительное число; для обоих процессов выполнение продолжается после вилки.

Детский процесс будет проходить через блок else if (pid == 0), а родитель будет запускать блок else.

3

После выполнения функции fork() у вас есть два процесса, которые продолжают выполняться после вызова fork. Единственное различие между этими двумя процессами - это возвращаемое значение fork(). В исходном процессе «родительский», возвращаемое значение является идентификатором процесса (pid) дочернего элемента. В новом клонированном процессе «ребенок» возвращаемое значение равно 0.

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

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

Смежные вопросы