execvp() - exit() return 函数中的值

execvp() - exit() return value in function

最近我一直在和下面的概念作斗争,我仍然无法理解它。我有这段代码

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)If execvp succeeds, it does not return any value. If it fails it returns -1 (I think this return value does not have to do anything with my foo function).

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

据我了解,如果execvp成功,foo应该return-1(根据变量fail),如果失败则应该return 0,但这不是我的 printf 检查 main 函数显示的内容。其实结果总是和我想的相反

PS:我发现了一些关于 execvp 错误处理的东西,使用了很好的旧 shelf-pipe 技巧,但它对我来说太吵了。我想要一种更简单的方法来处理错误。

execvp 用你正在exec的那个覆盖你的整个过程

如果 execvp 成功,则 fail 变量不再存在于 child 中。 foo 函数不再存在于 child 中。 child 中不再存在调用 foo 的函数。如果 execvp 成功,那么 child 现在是 运行 一个 不同程序的 main 函数。

最终该程序将退出,然后 child 进程退出。它永远不会回到您的程序。 (这就是为什么您需要创建一个单独的进程来调用 execvp 的原因 - 如果您使用原始进程,您将永远无法取回它)

The question is: what is the output of function foo?

您似乎在问 foo()return 值 是什么。 "Output" 通常是指写入终端或外部文件的数据。但问题仍然存在:在哪个过程中?假设 fork() 成功,那么你有两个几乎相同的进程,都执行 foo().

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

如果 execvp() 成功,它根本 return

If it fails it returns -1 (I think this return value does not have to do anything with my foo function).

是的。但是,只有您的 child 进程执行 execvp(),并且如果它 returns,该进程最终会调用 exit().

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

这会在进程从 foo() 开始 return 之前终止进程,因此在 child 进程中 foo() 永远不会 return,是否 execvp 成功与否。控制不会return到parent。分叉进程与调用函数完全不同。 parent 可以通过 waitpid() 调用了解 child 的退出代码。

在 parent 中,如果 fork() 失败,那么该进程也会调用 exit(),因此不会 return 来自 foo()。另一方面,假设 fork() 成功,parent 等待 child 终止。 child 是一个单独的进程,有它自己的所有变量副本,因此无论它对其 fail 副本所做的任何事情都不会影响 parent。也就是说,分叉一个 child 进程也不像在同一进程中启动一个线程。

由于parent本身不修改fail,如果达到

,它仍然有初始值10
    if (fail == 1){

10 != 1,所以如果 foo() 做 return 那么它 returns 0.