gpt4 book ai didi

c - 如何正确等待 execve 完成?

转载 作者:太空狗 更新时间:2023-10-29 12:28:26 25 4
gpt4 key购买 nike

C 源代码(编译并运行 Linux Centos 6.3)有一行:

execve(cmd, argv, envp);

execve 没有返回,但是我想修改代码知道什么时候完成。所以我这样做:

if (child = fork()) {
waitpid(child, NULL, 0);
/*now I know execve is finished*/
exit(0);
}

execve(cmd, argv, envp);

当我这样做时,生成的程序在 99% 的时间里都能正常工作,但很少出现奇怪的错误。

上面的有什么问题吗??我希望上面的代码像以前一样精确运行(除了慢一点)。我说得对吗?

如果想知道背景,修改后的代码是dashexecve 调用用于在 dash 找出要运行的字符串后运行一个简单的命令。当我按照上面的方式精确修改(等待后甚至没有运行任何东西)并在修改后的破折号下重新编译和运行程序时,大多数时候它们运行良好。然而,重新编译一个名为“biosutility”的特定内核模块给我这个错误

cc1: error: unrecognized command line option "-mfentry"

最佳答案

仔细阅读 execve(2) 的文档和 fork(2)waitpid(2) . execvefork 都很棘手, fork很难理解。我强烈建议阅读 Advanced Linux Programming (可在线免费获得,但您可以购买纸质书)其中有几章来解决这些问题。

(不要害怕花几天时间阅读和理解这些系统调用,它们很棘手)

一些要点。

  • 每个 system call 可能会失败,您应该始终处理它的失败,至少通过使用 perror(3) 显示一些错误消息并立即 exit(3) -ing.

  • execve(2) 系统调用通常从不返回,因为它失败时返回(成功时,它不会返回,因为调用程序已经被替换掉了!)因此大多数对它的调用(和类似的 exec(3) 函数)通常是这样的:

    if (execve(cmd, argv, envp)) { perror (cmd); exit(127); };
    /* else branch cannot be reached! */

    通常在 execve 失败时使用奇怪的退出代码,如 127(通常未使用,除了上面的代码),而且通常你无法做任何其他事情。当(几乎总是)与 fork 一起使用时,您通常会在 child 进程中调用 execve

  • fork(2)系统调用在成功时返回两次(一次在父进程中,一次在子进程中)。这很难理解,请阅读我提供的引用资料。它仅在失败时返回一次。所以你总是保留fork的结果,所以典型的代码是:

     pid_t pid = fork ();
    if (pid<0) { // fork has failed
    perror("fork"); exit(EXIT_FAILURE);
    }
    else if (pid==0) { // successful fork in the child process
    // very often you call execve in child, so you don't continue here.
    // example code:
    if (execve(cmd, argv, envp)) { perror (cmd); exit(127); };
    // not reached!
    };
    // here pid is positive, we are in the parent and fork succeeded....
    /// do something sensible, at some point you need to call waitpid and use pid

建议:使用strace(1)在某些程序上,也许可以尝试 strace -f bash -c 'date; pwd' 并研究输出。它提到了很多syscalls(2) ....

您的示例代码可能(有时)只需添加一些 else 就可以工作

// better code, but still wrong because of unhandled failures....
if ((child = fork())>0) {
waitpid(child, NULL, 0);
/*now I know execve is finished*/
exit(0);
}
/// missing handling of `fork` failure!
else if (!child) {
execve(cmd, argv, envp);
/// missing handling of `execve` failure
}

但该代码仍然不正确,因为未处理故障。

关于c - 如何正确等待 execve 完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34625123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com