4

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

我为 SIGINT 编写了一个信号处理程序,它杀死了前台进程。唯一的问题是,如果我有一个后台进程,它也会杀死它。据我了解,当按下 Control-C 时,SIGINT 会通过一个队列传递给不同的进程,如果有一个处理它,那么它就会停止。我的外壳应该正在处理它,所以它不应该被传递给后台进程,对吧?

这是我的代码:

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,什么都不会发生。但是后台进程被杀死了。

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

4

0 回答 0