execvp () - exit () возвращаемое значение в функции - PullRequest
0 голосов
/ 17 января 2019

В последнее время я боролся со следующей концепцией и до сих пор не могу ее понять. У меня есть этот блок кода

int foo(int f){
    int fail = 10;  //some random initialization value
    int status;
    pid_t child_pid;
    child_pid = fork();

    if(child_pid == 0) {
        /* This is done by the child process. */

        if (execvp(tokens2[0], tokens2)<0){
            fail =1;
            perror(tokens2[0]); 
            exit(1);
        }
    }else if(child_pid<0){
        perror("Fork failed");
        exit(1);
    } else {
        waitpid(child_pid, &status, WUNTRACED);
    }

    //handle execvp error return value
    if (fail == 1){
        return -1;
    }else{
        return 0;
    }

}

Это не имеет большого смысла (не обращайте внимания на tokens2[] массив, он объявлен правильно и работает просто отлично), потому что он находится в абстрактной форме, чтобы его было слышно и легко понять. Вопрос в том, что выдает функция foo? Вот к чему я так далеко пришел:

1) Если execvp успешен, он не возвращает никакого значения. Если он не работает, он возвращает -1 (я думаю, что это возвращаемое значение не должно ничего делать с моей foo функцией).

2) exit(1) убивает дочерний процесс и возвращает поток управления родительскому процессу.

В моем понимании, если execvp успешен, foo должен вернуть -1 (в соответствии с переменной fail), если он потерпит неудачу, он должен возвратить 0, но это не то, что мой printf проверяет главную функцию show. На самом деле результат всегда противоположен тому, что я ожидаю.

PS: Я нашел кое-что о execvp обработке ошибок, используя старый добрый шельфовый трюк, но он слишком шумный для меня. Я хочу более простой способ справиться с ошибкой.

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Вопрос в том, что выдает функция foo?

Вы, похоже, спрашиваете, что является возвращаемым значением из foo(). «Вывод» обычно относится к данным, записанным в терминал или во внешний файл. Но остается вопрос: в каком процессе? Предположим, что fork() успешен, тогда у вас есть два практически идентичных процесса, каждый из которых выполняет foo().

1)If execvp succeeds, it does not return any value.

Если execvp() завершается успешно, он вообще не возвращает .

Если это не удается, он возвращает -1 (я думаю, что это возвращаемое значение не должно ничего делать с моей функцией foo).

Да. Однако только ваш дочерний процесс выполняет execvp(), и в случае возврата он завершает вызов exit().

2)exit(1) kills the child process and returns the control flow to the parent.

Это завершает процесс, прежде чем он когда-либо вернется из foo(), поэтому в дочернем процессе foo() никогда не возвращается, независимо от того, успешно ли execvp или нет. Элемент управления не возвращает родителю. Формирование процесса совсем не то же самое, что вызов функции. Родитель может узнать код выхода ребенка с помощью вызова waitpid().

В родительском , если fork() завершается ошибкой, этот процесс также вызывает exit() и, следовательно, не возвращается из foo(). Предположим, что fork() завершается успешно, с другой стороны, родитель ожидает, пока дочерний процесс завершится. Дочерний процесс - это отдельный процесс, со своей собственной копией всех переменных, поэтому все, что он мог сделать со своей копией fail, не влияет на родителя. То есть разветвление дочернего процесса не похоже на запуск потока в том же процессе.

Поскольку родительский элемент сам не изменяет fail, он по-прежнему имеет свое начальное значение 10, если он достигает

    if (fail == 1){

10! = 1, поэтому, если foo() вернется, то вернется 0.

0 голосов
/ 17 января 2019

execvp заменяет весь ваш процесс на тот, который вы exec ing.

Если execvp успешно, переменная fail больше не существует в дочернем элементе. Функция foo больше не существует в дочернем элементе. Функция, которая вызвала foo, больше не существует в дочернем элементе. Если execvp завершается успешно, то теперь ребенок запускает функцию другой программы main.

В конечном итоге эта программа завершится, а затем завершится дочерний процесс. Это никогда не возвращается к вашей программе. (Вот почему вам нужно создать отдельный процесс для вызова execvp in - если вы использовали оригинальный процесс, вы никогда не получите его обратно)

...