Должен ли я завершать разветвленный дочерний процесс с помощью exit()?

Я работаю над некоторыми вещами, используя fork() в C. Это мой первый контакт с концепцией разветвления процессов.

В общем, у меня что-то вроде этого:

int pid;

pid = fork();
if (pid < 0) {
    fprintf(stderr, "Fork Failed");
    exit(-1);
} else if (pid == 0) {
    fprintf(stderr, "Inside child %d\n", getpid());
    // do some other stuff
    exit(0);
} else {
    fprintf(stderr, "Inside parent %d\n", getpid());
}

Раньше я не ставил exit(0) в код дочернего процесса. Я получал, казалось бы, тонны повторяющихся процессов. Я добавил exit(0), и теперь я создаю только одного ребенка. Тем не менее, я хочу знать, является ли это правильной практикой или просто пластырем. Правильно ли это делать. Как ребенок должен «остановиться», когда все сделано?


person n0pe    schedule 01.02.2014    source источник
comment
Как должно останавливаться что-либо, когда оно сделано?   -  person Kerrek SB    schedule 01.02.2014
comment
Разветвленный процесс — это такой же процесс, как и любой другой. Он завершится, когда основная функция выйдет, или при явном вызове exit(), или при неисправимой ошибке/исключении.   -  person kuroi neko    schedule 01.02.2014
comment
Я не уверен, как вы получили тонны процессов без цикла.   -  person ooga    schedule 01.02.2014


Ответы (2)


Обычно потомок либо имеет собственный код с exit, либо вызывает одну из функций exec, чтобы заменить образ своего процесса другой программой. Так что с выходом все в порядке. Но родитель и дочерний элемент могут выполнять хотя бы часть одного и того же кода, например:

int pid = fork();
if (pid < 0) {
    fprintf(stderr, "Fork Failed");
    exit(-1);
} else if (pid == 0) {
    // child code
} else {
   // parent code
}
// shared code
person ooga    schedule 01.02.2014
comment
Итак, это расширение моего вопроса. Когда дочерний процесс заканчивает свой код и переходит к общему коду, выходит ли он из этой функции и продолжает выполнять остальную часть программы? Допустим, код, который вы написали выше, был в makeAFork(), будет ли потомок после запуска общего кода возвращаться из makeAFork() и продолжать выполнять что-то? - person n0pe; 01.02.2014
comment
Ребенок продолжает идти туда, куда ведет код. Помните, что ребенок — это отдельная (почти) идентичная копия родителя. Возвращаемое значение fork() — это все, что их действительно отличает (конечно, они также имеют разные pid, и есть несколько других деталей, которые могут отличаться). - person ooga; 01.02.2014

Что ж, если вы хотите, чтобы родительский процесс работал только после завершения дочернего процесса, вы можете использовать функцию ожидания. Вот пример:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h> //fork() is defined in this header file
#include<sys/wait.h>//wait() is defined in this header file
int main()
{
    int pid,a,b;
    printf("\nPlease enter two numbers\n");
    scanf("%d%d",&a,&b);
    pid=fork();
    if(pid<0)
    {
        printf("\nfork failed\n");
        exit(1);
    }
    if(pid==0)
    {
        //you are in chiled process
        //getting child process id
        printf("\n[child %d]: sum of %d and %d is %d\n",getpid(),a,b,a+b);
    }
    else
    {
        //waiting for child process to finish
        wait(NULL);
        //getting parent id
        printf("\n[parent %d]:difference of %d and %d is %d\n",pa_pid,a,b,a-b);
        exit(0);
    }
}
person Prashant Anuragi    schedule 01.02.2014
comment
Обратите внимание, что fork() определяется в <unistd.h>, а не в <sys/types.h>. Также обратите внимание, что в современных версиях POSIX-совместимых систем (то есть созданных в текущем тысячелетии, а не в прошлом тысячелетии — грубо говоря) вам не нужно явно включать <sys/types.h>. Вреда не будет, но это и не нужно. Другие заголовки POSIX либо включают его, либо включают другие заголовки, определяющие соответствующие типы, которые должен определить <sys/types.h>. Это признак кодирования «старой школы». Для его включения могут быть причины, например, корпоративные стандарты кодирования или устаревшие системы, которые необходимо поддерживать, но… - person Jonathan Leffler; 19.07.2015
comment
Код вашего дочернего процесса использует неявный return 0; в конце main(); ваш родительский процесс использует явный exit(0); для выхода из main(). Если бы это был мой код, в конце main() был бы явный return 0;, а не прямой exit(0) для родительского потока. Дочерний код будет в своей собственной функции, которая, вероятно, будет заканчиваться явным exit(0); Я мог бы даже украсить дочернюю функцию C11 _Noreturn, чтобы показать, что она не возвращается. - person Jonathan Leffler; 19.07.2015