信号之作业控制信号
在表10-1(http://www.cnblogs.com/nufangrensheng/p/3514157.html)所示的信号中,POSIX.1认为有6个与作业控制有关:
SIGCHLD 子进程已停止或终止。
SIGCONT 如果进程已停止,则使其继续运行。
SIGSTOP 停止信号(不能被捕捉或忽略)。
SIGTSTP 交互式停止信号。
SIGTTIN 后台进程组成员读控制终端。
SIGTTOU 后台进程组成员写到控制终端。
除SIGCHLD以外,大多数应用程序并不处理这些信号:交互式shell则通常做处理这些信号的所有工作。当键入挂起字符(通常是Ctrl+Z)时,SIGTSTP被送至前台进程组的所有进程。当我们通知shell在前台或后台恢复运行一个作业时,shell向该作业中的所有进程发送SIGCONT信号。与此类似,如果向一个进程递送了SIGTTIN或SIGTTOU信号,则根据系统默认的方式停止此进程,作业控制shell了解到这一点后就通知我们。
在作业控制信号间有某种交互作用。当对一个进程产生四种停止信号(SIGTSTP、SIGSTOP、SIGTTIN或SIGTTOU)中的任意一种时,对该进程的任一未决SIGCONT信号就会被丢弃。与此类似,当对一个进程产生SIGCONT信号时,对同一进程的任一未决停止信号将被丢弃。
注意,如果进程是停止的,SIGCONT的默认动作是继续运行该进程,否则忽略此信号。通常,对该信号无需做任何事情。当对一个停止的进程产生一个SIGCONT信号时,该进程就继续运行,即使该信号是被阻塞或忽略的也是如此。
实例
程序清单10-22展示了当一个程序处理作业控制时所使用的规范代码序列。
#include "apue.h" #define BUFFSIZE 1024 static void sig_tstp(int); int main(void) { int p; char buf[BUFFSIZE]; /* * Only catch SIGTSTP if we're running with a job-control shell. */ if(signal(SIGTSTP, SIG_IGN) == SIG_DFL) signal(SIGTSTP, sig_tstp); while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) if(write(STDOUT_FILENO, buf, n) != n) err_sys("write error"); if(n < 0) err_sys("read error"); exit(0); } static void sig_tstp(int signo) /* signal handler for SIGTSTP */ { sigset_t mask; /* ... move cursor to lower left corner, reset tty mode ... */ /* * Unblock SIGTSTP, since it's blocked while we're handling it. */ sigemptyset(&mask); sigaddset(&mask, SIGTSTP); sigprocmask(SIG_UNBLOCK, &mask, NULL); signal(SIGTSTP, SIG_DFL); /* reset disposition to default */ kill(getpid(), SIGTSTP); /* and send the signal to ourself */ /* we won't return from the kill until we're continued */ signal(SIGTSTP, sig_tstp); /* reestablish signal handler */ /* ... reset tty mode, redraw screen ... */ }
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。