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

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

Ответы

Ответ 1

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

Синтаксис:

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

или

pid_t wait(int *status);

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


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

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

Ответ 2

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

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