我正在尝试在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,那么什么都不应该发生。但后台进程被杀死了。
我很想知道如何阻止后台进程被杀。有任何想法吗? :)