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