системные вызовы _exit(), fork() и waitpid()

Итак, я выхожу из дочернего потока обратно в родительский. Я использую системный вызов _exit(). Мне было интересно несколько вещей. Одним из них был параметр _exit для моего ребенка. Вот код, который выполняет мой дочерний процесс:

printf("\n****Child process.****\n\nSquence: ");

 do{
        //Print the integer in the sequence.
        printf("%d\t",inputInteger);
        if((inputInteger%2) == 0){
            //printf("inputInteger = %d\n", inputInteger);
            inputInteger = inputInteger / 2;
        }else{
            inputInteger = 3*inputInteger +1;
            //printf("%d\t",inputInteger);
        }

    }while(inputInteger != 1);

    //Makes sure we print off 1!
    printf("%d\n\n", inputInteger);

    //Properly exit
    _exit(status);

Я использую статус, потому что в своем родительском потоке я использую его в системном вызове waitpid(). Вот код родительского процесса, который выполняется после завершения дочернего процесса.

waitpid_check = waitpid(processID, &status, 0);
        printf("\n****Parent process.****\n");

        if(waitpid_check == -1){
            printf("Error in waitpid.\n");
            exit(EXIT_FAILURE);
        }

        if(WIFEXITED(status)){
            printf("Child process terminated normally!\n");
        }

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

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

Спасибо за вашу помощь!


person pmac89    schedule 18.02.2014    source источник
comment
Мы говорим о потоках или процессах? Судя по вызовам, вы имеете дело с дочерними процессами, а не с дочерними потоками.   -  person jia103    schedule 18.02.2014
comment
Да, я имею дело с процессами.   -  person pmac89    schedule 18.02.2014


Ответы (2)


Из руководства по линуксу для ожидания.

«Если статус не равен NULL, функции wait() и waitpid() сохраняют информацию о статусе в int, на который он указывает».

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

WIFEXITED(status)
returns true if the child terminated normally, that is, by calling exit(3) or _exit(2), or by returning from main().
WEXITSTATUS(status)
returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should only be employed if WIFEXITED returned true.
WIFSIGNALED(status)
returns true if the child process was terminated by a signal.
WTERMSIG(status)
returns the number of the signal that caused the child process to terminate. This macro should only be employed if WIFSIGNALED returned true.
WCOREDUMP(status)
returns true if the child produced a core dump. This macro should only be employed if WIFSIGNALED returned true. This macro is not specified in POSIX.1-2001 and is not available on some UNIX implementations (e.g., AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.
WIFSTOPPED(status)
returns true if the child process was stopped by delivery of a signal; this is only possible if the call was done using WUNTRACED or when the child is being traced (see ptrace(2)).
WSTOPSIG(status)
returns the number of the signal which caused the child to stop. This macro should only be employed if WIFSTOPPED returned true.
WIFCONTINUED(status)
(since Linux 2.6.10) returns true if the child process was resumed by delivery of SIGCONT.

Что касается того, правильно ли вы выходите из дочернего процесса, это действительно зависит. Вы бы вышли, как и в любой другой программе, поскольку, когда вы разветвляете процесс, вы действительно просто дублируете адресное пространство и дочерний процесс при запуске как собственную независимую программу (конечно, с теми же открытыми FD, уже объявленными значениями и т. д. как родитель) . Ниже приведена типичная реализация этой проблемы (хотя в ожидание передается NULL вместо статуса, поэтому я думаю, что вы все делаете правильно).

/* fork a child process */
pid = fork();

if (pid < 0) { /* error occurred */
    fprintf(stderr, "Fork Failed\n");
    return 1;
}
else if (pid == 0) { /* child process */
    printf("I am the child %d\n",pid);
    execlp("/bin/ls","ls",NULL);
}
else { /* parent process */
    /* parent will wait for the child to complete */
    printf("I am the parent %d\n",pid);
    wait(NULL);

    printf("Child Complete\n");
}

return 0;
person PandaRaid    schedule 18.02.2014
comment
Спасибо, я пропустил часть _exit(2) на странице руководства. Это был мой главный вопрос. Я просто не хотел показывать весь свой код, так как это задание. - person pmac89; 19.02.2014

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

Идея кажется хорошей на высоком уровне.

Следует иметь в виду одну вещь: вы можете захотеть окружить суть вашего дочернего метода в блоке try/catch. С потоками вы часто не хотите, чтобы исключение мешало вашему основному потоку.

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

person jia103    schedule 18.02.2014