C中后台子进程的无效命令

时间:2015-06-25 10:55:55

标签: c process fork parent execvp

我在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)。

2 个答案:

答案 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或其他异常终止条件终止,则父进程仍将其视为成功。