我正在制作一个小型shell
程序。我希望暂停sigtstp_handler
中的前台程序。sigchld_handler
收割zombie
。但是当我输入{{1}时即使我没有前台程序,ctrl z
仍然会获得SIGTSTP。
sigchld_handler
处理程序
Signal(SIGINT, sigint_handler); /* ctrl-c */
Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */
Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */
我只是void sigchld_handler(int sig)
{
int status;
pid_t pid;
while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0 ) {
if (WIFEXITED(status)) { /*checks if child terminated normally */
deletejob(jobs, pid);
}
if (WIFSIGNALED(status)) { /*checks if child was terminated by a signal that was not caught */
printf("Job [%d] (%d) terminated by signal %d\n", pid2jid(pid), pid, WTERMSIG(status));
deletejob(jobs,pid);
}
if (WIFSTOPPED(status)) { /*checks if child process that caused return is currently stopped */
getjobpid(jobs, pid)->state = ST;
printf("Job [%d] (%d) stopped by signal %d\n", pid2jid(pid), pid, WTERMSIG(status));
//printf("[%d] Stopped %s\n", pid2jid(pid), jobs->cmdline);
}
}
if (pid < 0 && errno != ECHILD) {
printf("waitpid error: %s\n", strerror(errno));
}
return;
}
void sigtstp_handler(int sig)
{
pid_t pid = fgpid(jobs);//Return PID of current foreground job, 0 if no such job
if (pid!=0){
struct job_t *p = getjobpid(jobs, pid);
printf("kill %d %s %d\n",p->pid,p->cmdline,p->state);
kill(pid,SIGTSTP);
}
return;
}
void sigint_handler(int sig)
{
pid_t pid = fgpid(jobs);
if (pid!=0){
struct job_t *p = getjobpid(jobs, pid);
printf("kill %d %s %d\n",p->pid,p->cmdline,p->state);
kill(pid,SIGINT);
}
return;
}
,在我setpgid(0,0)
子进程之后,然后解决了这个问题。但我不知道究竟发生了什么......
答案 0 :(得分:0)
您必须拥有前台进程(如果您使用终端)。如果你没有启动子进程,那么shell本身就处于前台状态,TSTP
的接收者也是如此。
前台/后台管理需要的工作多于信号处理。您需要设置进程组并声明哪个组是前台组。
基本任务是:
setpgid
)tcsetpgrp
)SIGCHLD
和状态WIFSTOPPED
/ WSTOPPED
并相应地管理您的工作清单SIGTSTP
不敏感(忽略shell中的此信号)工作控制是一项艰巨的任务......请仔细阅读文档。