6

我想将退出状态 0 从 execve 进程发送到启动它的进程。因为在 Success execve 永远不会返回,所以在那之后我无法做任何事情。但我想如果 execve 运行成功。

4

2 回答 2

6

您可以使用以下命令验证 exec 是否成功FD_CLOEXEC

  • 创建一个管道。

  • 叉子。

  • 在孩子中,关闭管道的读取端并在管道FD_CLOEXEC的写入端设置标志。然后继续exec。如果exec成功,管道将自动关闭FD_CLOEXEC。如果exec失败,将一个字节写入管道并退出。

  • 在父级中,关闭管道的写入端并从读取端读取。如果你读到了 0 个字节(EOF),就说明exec成功了。如果您在管道中读取一个字节,则意味着exec失败。

发生故障时通过管道写入的数据可用于传输错误信息,例如errnoafter的值exec

为简洁起见省略了错误检查的代码如下所示:

int pipe_fds[2];
pipe(pipe_fds);
if (!fork()) {
  close(pipe_fds[0]);
  fcntl(pipe_fds[1], F_SETFD, F_CLOEXEC);
  execve(...);
  write(pipe_fds[1], "", 1);
  _exit(1);
}
else {
  int n;
  char out;
  close(pipe_fds[1]);
  n = read(pipe_fds[0], &out, 1);
  if (n == 0)
    printf("exec successful\n");
  else
    printf("exec failed\n");
  close(pipe_fds[0]);
}

请注意,如果其他线程可能并行执行自己的进程,则此技术可能不安全。问题是在创建管道和设置 close-on-exec 标志之间存在延迟。如果在该关键窗口期间不相关的线程分叉和执行,则子线程将继承pipe_fds[1]并且不会关闭它,从而导致父线程挂起。这可以使用特定于 Linux 的pipe2调用来修复,该调用允许使用 close-on-exec 标志集原子地创建管道。

于 2013-03-19T10:50:21.217 回答
2

等待您fork()完成启动的进程,您可以使用wait()

/* parent */
int status;
while (wait(&status) != uproc.pid) {
    printf("waiting for child to exit");
    }

并基于这个问题

子进程的退出状态由wait函数在status变量中提供。

您可以使用WEXITSTATUS宏获得退出状态,但前提是程序正常退出(即exit从其main函数调用或返回):

if (WIFEXITED(status))
    printf("Child exit status: %d\n", WEXITSTATUS(status));
else
    printf("Child exited abnormally\n");
于 2013-03-19T10:50:07.747 回答