著名的自管技巧可以适用于这一目的。
#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <string.h>#include <sys/wait.h>#include <sysexits.h>#include <unistd.h>int main(int argc, char **argv) { int pipefds[2]; int count, err; pid_t child; if (pipe(pipefds)) { perror("pipe"); return EX_OSERR; } if (fcntl(pipefds[1], F_SETFD, fcntl(pipefds[1], F_GETFD) | FD_CLOEXEC)) { perror("fcntl"); return EX_OSERR; } switch (child = fork()) { case -1: perror("fork"); return EX_OSERR; case 0: close(pipefds[0]); execvp(argv[1], argv + 1); write(pipefds[1], &errno, sizeof(int)); _exit(0); default: close(pipefds[1]); while ((count = read(pipefds[0], &err, sizeof(errno))) == -1) if (errno != EAGAIN && errno != EINTR) break; if (count) { fprintf(stderr, "child's execvp: %sn", strerror(err)); return EX_UNAVAILABLE; } close(pipefds[0]); puts("waiting for child..."); while (waitpid(child, &err, 0) == -1) if (errno != EINTR) { perror("waitpid"); return EX_SOFTWARE; } if (WIFEXITED(err)) printf("child exited with %dn", WEXITSTATUS(err)); else if (WIFSIGNALED(err)) printf("child killed by %dn", WTERMSIG(err)); } return err;}这是一个完整的程序。
$ ./a.out foo孩子的execvp:没有此类文件或目录$(sleep 1 && killall -QUIT sleep&); 外出睡眠60等待孩子...被3杀死的孩子$ ./a.out true等待孩子...孩子以0退出
工作原理:
创建一个管道,并创建write端点
CLOEXEC:
exec成功执行an时,它将自动关闭。
在孩子中,尝试
exec。如果成功,我们将不再具有控制权,但管道已关闭。如果失败,则将失败代码写入管道并退出。
在父级中,尝试从另一个管道端点读取。如果
read返回零,则说明管道已关闭并且子级必须
exec成功。如果
read返回数据,那是我们孩子编写的失败代码。



