ctrl-c在我的shell中杀死我的后台进程

时间:2013-08-15 01:37:47

标签: c shell signals control-c

我正在尝试在C中编写一个基本的shell。我需要做的一件事就是能够同时拥有后台和前台进程。 Control-C必须终止前台进程(如果有的话),并且不得终止任何后台进程。

我为SIGINT编写了一个杀死前台进程的信号处理程序。唯一的问题是,如果我有一个后台进程,它也会杀死它。根据我的理解,当按下Control-C时,SIGINT会向队列传递给不同的进程,如果有人处理它,那么就是它停止的地方。我的shell应该处理它,所以它不应该传递给后台进程吗?

这是我的代码:

pid_t foreground_pid;

int main(int argc, char *argv[]) {
    signal(SIGINT, INThandler);
    char *buf;

    while(1) {
        fgets(buf, 128, stdin);

        */ error checking */
        */ split buf into null terminated char* array (arg_array) 
           and count the number of args (num_args) */

        handlerCommand(buf, arg_array, num_args);

        zombieTerminator();
}

void handleCommand(char *command, char **args, int num) {
    pid_t pid;

    if ((pid = fork()) < 0)
        printf("error\n");
    else if (pid == 0) { // Child
        if (!strcmp(args[num-1], "&")) {
            /* redirect stdin to /dev/null */
        }

        execvp(args[0], args);
        printf("error\n");
        exit(127);
    }

    // parent - either wait (foreground) or continue (background)
    if (!strcmp(args[num-1], "&")) {    
        printf(" [%ld] : %s\n", (long)pid, command);
    } else {
        foreground_pid = pid;
        if ((pid = waitpid(pid, &status, 0)) < 0) 
            fprintf(stderr, "waitpid error\n");
    }

    return;
}

/** Terminates any zombie processes that finished in the background */
void zombieTerminator(void) {
    int status;
    pid_t pid;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if (pid != foreground_pid) {
            printf(" [%ld] exited with status: %d\n", (long)pid, 
                    WEXITSTATUS(status));
        }
    }
}

/** Handles the control-c signal from the keyboard */
void INThandler(int sig) {
    if (foreground_pid) {
        kill(foreground_pid, SIGKILL);
        foreground_pid = 0;
    } else {
        printf("\n%s\? ", cwd);
    }
    fflush(stdout);
}

当我运行前台进程时:

sleep(100)

然后我可以点击contorl-c它会退出。喜欢它应该。但是,如果我运行后台进程:

sleep(100) &

我得到了一个新的提示,就像我应该的那样,但如果我点击了control-c,那么什么都不应该发生。但后台进程被杀死了。

我很想知道如何阻止后台进程被杀。有任何想法吗? :)

1 个答案:

答案 0 :(得分:1)

经过大量搜索,我找到了这个问题的答案。请参考这个问题: Child process receives parent's SIGINT