我在C中有以下代码:
if ((childpid = fork()) == 0) {
if (execvp(argv[0], argv) < 0) {
//execute failed
exit(1);
}
} else if (childpid < 0) {
//fork failed
} else {
//if execvp failed don't do anything here
//else do something
}
我想要的是:
我输入一个命令。
如果它不可执行,它不应该做任何事情,只能等待我下一个输入的命令。
如果它是可执行的,它应该在父进程中做一些事情。
如果我输入例如sleep 1m
它应该在我的子进程中执行它,在父进程中执行操作并且应该仍然能够执行更多的工作(这很好)。但是当我执行类似abcdef
(无效命令)之类的东西时,无论如何它都会在父进程中执行。
有人可以告诉我代码应该是什么样的吗?
我也尝试了以下内容:
void signalHandler(int signal)
{
if (signal==SIGCHLD) {
printf("Child ended\n");
wait(NULL);
}
}
//in main
signal(SIGCHLD,signalHandler);
//...
if ((childpid = fork()) == 0) {
if (execvp(t_argv[0], t_argv) < 0) {
kill(getppid(),SIGCHLD);
}
}
这是对的吗? 这样我之后就会收到错误(当它完成时)。
waitpid(childpid, &status, WNOHANG)
告诉我它完成了一个错误(-1)。
答案 0 :(得分:0)
一种可能的解决方案是使用一对匿名管道,其中子进程在管道的写入端写入需要传递给父级的任何状态。然后在父级中检查管道的读取端,如果在子进程退出之前没有收到任何内容,那么一切正常并且子进程已成功执行该程序。
如果父进程在子进程退出之前确实收到任何内容,则表示exec
调用失败。
答案 1 :(得分:0)
一种可能的解决方案是使用信号异常终止(例如,SIGUSR1
)并检查父级中的信号。这假设您在孩子中执行的任何程序都不会以SIGUSR1
结束 - 在大多数情况下这是一个合理的假设,我会说。然后父母可以检查孩子的终止状态。
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
pid_t childpid;
if ((childpid = fork()) == 0) {
if (execvp(argv[1], &argv[1]) < 0) {
raise(SIGUSR1);
}
} else if (childpid < 0) {
perror("fork()");
exit(EXIT_FAILURE);
} else {
int term_status;
if (wait(&term_status) < 0) {
perror("wait()");
exit(EXIT_FAILURE);
}
if (WIFSIGNALED(term_status) && WTERMSIG(term_status) == SIGUSR1) {
printf("execvp failed\n");
} else {
printf("success\n");
}
}
return 0;
}
附注:你可能想要execvp(argv[1], &argv[1])
,因为execvp(argv[0], argv)
会一遍又一遍地执行同一个程序。
同样,只要execvp(2)
执行的流程永远不会以SIGUSR1
终止,这就有效。请注意,如果execvp(2)
执行的进程以SIGSEGV
或其他异常终止条件终止,则父进程仍将其视为成功。