Как выйти из дочернего процесса и вернуть его статус из execvp()?

StackOverflow https://stackoverflow.com/questions/903864

  •  05-09-2019
  •  | 
  •  

Вопрос

В моей простой пользовательской оболочке я считываю команды из стандартного ввода и выполняю их с помощью 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), что будет означать, что дочерний процесс всегда будет иметь состояние "OK".

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

Это было полезно?

Решение

Вам нужно использовать 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 сам по себе сбой, но тогда сбой происходит не из-за того, что новая программа завершилась.Это потому, что он никогда не запускался с самого начала.

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

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top