Как выйти из дочернего процесса и вернуть его состояние из execvp ()? - PullRequest
16 голосов
/ 24 мая 2009

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

Примерно так:

pid = fork();

if(pid == -1) {
    perror("fork");
    exit(1);
}

if(pid == 0) {
    // CHILD PROCESS CODE GOES HERE...
    execvp(pArgs[0], pArgs);
    exit(0);
} else {
    // PARENT PROCESS CODE GOES HERE...
}

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

Как я могу вернуть правильный статус из вызова execvp () и поместить его в вызов exit ()? Должен ли я просто получить значение int, которое возвращает execvp (), и передать его в качестве аргумента exit () вместо 0. Это достаточно и правильно?

Ответы [ 3 ]

16 голосов
/ 24 мая 2009

Вам нужно использовать waitpid(3) или wait(1) в родительском коде, чтобы дождаться выхода ребенка и получить сообщение об ошибке.

Синтаксис:

pid_t waitpid(pid_t pid, int *status, int options);

или

pid_t wait(int *status);

status содержит статус выхода. Посмотрите на справочные страницы , чтобы узнать, как его разобрать.


Обратите внимание, что вы не можете сделать это из дочернего процесса. После вызова execvp дочерний процесс умирает (для всех практических целей) и заменяется на exec d процесс. Единственный способ достичь exit(0) - это если сам по себе execvp потерпит неудачу, но тогда причина не в том, что новая программа закончилась. Это потому, что он никогда не запускался с самого начала.

Редактировать: дочерний процесс не действительно не умирает. PID и среда остаются неизменными, но весь код и данные заменяются процессом exec. Вы можете рассчитывать на , а не , возвращаясь к исходному дочернему процессу, если только exec завершится неудачей.

3 голосов
/ 24 мая 2009

Используйте wait() или waitpid() в родительском процессе. Пример здесь: Код возврата, когда ОС убивает ваш процесс .

Кроме того, когда умирает ребенок, в родительский процесс отправляется сигнал SIGCHLD.

3 голосов
/ 24 мая 2009

По вашему вопросу немного сложно понять, о чем вы спрашиваете. Поэтому я попытаюсь осветить пару связанных вопросов:

  • execvp() либо не возвращается (при успехе), либо возвращает ошибку. Это означает, что ваш дочерний код должен обрабатывать только ошибки. Ваш дочерний код должен зафиксировать результат execvp() и использовать это значение в exit(), как вы предложили. Ваш дочерний код никогда не должен возвращать 0, поскольку единственный успех означает, что execvp сработало и , что процессы вернут 0 (или нет).
  • Родитель может получить дочернюю информацию от waitpid() о своем статусе выхода. Существует несколько макросов, определенных для извлечения информации из возвращенного параметра status. Для вашей цели WIFEXITED сообщает вам, вышел ли ребенок "нормально", и WEXITSTATUS, чтобы получить статус ребенка в том виде, в каком он был передан exit(). См. Справочную страницу waitpid для других макросов.
...