我正在尝试构建一个shell,并且我已经设法编写了大部分功能,但是我遇到了一个小问题。
说我输入firefox &
。 Firefox将作为后台进程打开。 &
激活BG标志,使父母不等待子进程。
然后我输入gedit
。 Gedit将作为前台进程打开。这意味着当前父级正在等待进程关闭。
此时,父级有两个进程 - firefox
和gedit
。 Firefox尚未等待,目前处于后台,而我们目前正在等待Gedit完成。到目前为止一切都很好。
但是,如果我决定按ctrl-c
发送SIGINT信号,则firefox
和gedit
都会关闭。不好,只有gedit
应该关闭。
这是我的信号处理函数:
pid_t suspended_process[10];
int last_suspended = -1;
void signal_handler(int signo){
pid_t process = currentpid();
// Catches interrupt signal
if(signo == SIGINT){
int success = kill(process, SIGINT);
}
// Catches suspend signal
else if(signo == SIGTSTP){
int success = kill(process, SIGTSTP);
resuspended = 1;
suspended_process[last_suspended+1] = process;
last_suspended++;
}
}
这是fork-exec代码中的一部分,它可以等待进程,也可以继续运行。
else if(pid > 0){ //Parent
current_pid = pid;
// Waits if background flag not activated.
if(BG == 0){
// WUNTRACED used to stop waiting when suspended
waitpid(current_pid, &status, WUNTRACED);
if(WIFEXITED(status)){
setExitcode(WEXITSTATUS(status));
}
else if(WIFSIGNALED(status)){
printf("Process received SIGNAL %d\n", WTERMSIG(status));
}
}
}
如果我事先暂停某个流程,也会发生这种情况。例如,我运行firefox
,然后按ctrl-z
暂停它。然后我运行gedit
并按ctrl-c
关闭它。之后,如果我按fg
恢复已暂停的firefox
,则会立即关闭。
我找不到只将SIGINT信号发送到前台进程的方法,它总是将信号发送给除父级以外的所有子级,无论它们是在后台还是暂停。
以防万一,这是初始化信号处理程序的函数:
void init_handler(){
struct sigaction sa;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
// If conditions for signal handling.
// Also creates 2 signal handlers in memory for the SIGINT and SIGTSTP
if(sigaction(SIGINT, &sa, NULL) == -1)
printf("Couldn't catch SIGINT - Interrupt Signal\n");
if(sigaction(SIGTSTP, &sa, NULL) == -1)
printf("Couldn't catch SIGTSTP - Suspension Signal\n");
}