我想从execve进程向启动它的进程发送退出状态0。因为成功的execve永远不会返回,所以在此之后我将无法执行任何操作。但是如果execve运行成功,我希望能够发送退出状态0。
FD_CLOEXEC
验证执行成功:
创建一个管道。
分叉。
在子进程中,关闭管道的读端并在管道的写端上设置FD_CLOEXEC
标志。然后继续执行exec
。如果exec
成功,则由于FD_CLOEXEC
,管道将自动关闭。如果exec
失败,则向管道写入一个字节并退出。
在父进程中,关闭管道的写端并从读端读取。如果您读取0个字节(EOF),则表示exec
成功。如果您在管道中读取一个字节,则表示exec
失败。
失败时在管道上写入的数据可用于传输错误信息,例如exec
后的errno
值。
出于简洁起见,省略了错误检查的代码如下:
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]);
}
pipe2
调用来解决此问题,该调用允许原子地创建具有close-on-exec标志的管道。exec
失败时,是否保证在子进程关闭管道导致EOF通知之前会传递SIGCHLD信号?我喜欢这种技术背后的想法;我只是想知道是否存在竞争条件。 - Jonathan Lefflerexec
失败,通过管道发送一些数据就足够消除歧义了。 - user4815162342SIGCHLD
。 - user4815162342fork()
创建的文件描述符视图将不会关闭,因此父进程中的read()
实际上会挂起!这可以使用Linux特定的pipe2
调用来修复,该调用允许原子地创建带有close-on-exec标志的管道。 - user4815162342如果你想要等待通过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");
exec
是否成功,只是程序以成功的状态退出。当执行长时间运行的程序时,这可能会有所不同。 - user4815162342
exec
成功执行。exec
失败可以通过多种方式向父进程报告(通过管道或特殊退出状态),但是确认exec
成功更加困难,因为成功的exec
定义意味着我们的进程不再运行。 - user4815162342exec
..." 指的是创建子进程本身的exec
还是由子进程执行的exec
(该子进程又是由父进程执行exec
创建的)? - alkexec
不会创建子进程,而是fork
。所谓“子进程的exec
”指的是在子进程中执行的exec
。 - user4815162342