我想将退出状态 0 从 execve 进程发送到启动它的进程。因为在 Success execve 永远不会返回,所以在那之后我无法做任何事情。但我想如果 execve 运行成功。
2 回答
您可以使用以下命令验证 exec 是否成功FD_CLOEXEC
:
创建一个管道。
叉子。
在孩子中,关闭管道的读取端并在管道
FD_CLOEXEC
的写入端设置标志。然后继续exec
。如果exec
成功,管道将自动关闭FD_CLOEXEC
。如果exec
失败,将一个字节写入管道并退出。在父级中,关闭管道的写入端并从读取端读取。如果你读到了 0 个字节(EOF),就说明
exec
成功了。如果您在管道中读取一个字节,则意味着exec
失败。
发生故障时通过管道写入的数据可用于传输错误信息,例如errno
after的值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 标志集原子地创建管道。
等待您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");