我很困惑如何在这个使用 fork() 克隆进程的示例函数中处理这个 execvp()

I'm confused how this execvp() is handled in this sample function which uses fork() to clone a process

我从一本名为 "Advanced Linux Programming" 的书中获得了以下功能。

int spawn (char* program, char** arg_list)
{
    pid_t child_pid;

    /* Duplicate this process. */
    child_pid = fork ();

    if (child_pid != 0)
    /* This is the parent process. */
    return child_pid;

    else {
    /* Now execute PROGRAM, searching for it in the path. */
    execvp (program, arg_list);

    /* The execvp function returns only if an error occurs. */
    fprintf (stderr, “an error occurred in execvp\n”);
    abort ();
    }
}

但令我感到困惑的是,在 ls 执行成功的情况下,不会打印错误,但如果失败,它会打印放在其后一行的错误。

我的问题 fprintf (stderr, “an error occurred in execvp\n”);这一行是在execvp()函数之后,预计会在execvp()执行完之后执行,其实不然,只有在execvp() 遇到错误。函数 spawn() 似乎在成功执行 execvp() 后就结束了。我说得对吗?

您可以查看 execvp 的联机帮助页,上面写着:

The exec() family of functions replaces the current process image with a new process image.

那么,这是什么意思?这意味着,如果 execvp 成功,您的程序将不再在内存中,因此它永远不会到达错误消息。您在内存中的程序将被新程序替换(在您的情况下 ls 如果我理解正确的话)。

因此,如果您的程序能够打印出错误消息,则 execvp 函数将失败。否则其他程序开始执行。

你的程序仍然运行的原因是fork命令,它创建了进程映像的副本,所以你将有两个相同的进程运行只有一个将被您尝试执行的命令替换。这是通过 if 子句 if (child_pid != 0) 实现的,因为 fork 命令将复制进程和 return 新进程 ID (PID)。如果将其设置为 0(参见 man 3 fork),则它是新的子进程,如果它是 != 0 则它是父进程。如果它是子进程,您的函数只执行 execvp,父进程遇到早期的 return.