分类:
2008-12-08 12:18:47
10.20 job-control
signals
SIGCHLD |
Child process has stopped or terminated. |
SIGCONT |
Continue process, if stopped. |
SIGSTOP |
Stop signal (can't be caught or ignored). |
SIGTSTP |
Interactive stop signal. |
SIGTTIN |
Read from controlling terminal by member of a background process group. |
SIGTTOU |
Write to controlling terminal by member of a background process group. |
SIGTSTP中TSTP的意思是tty stop,即在control terminal上输入了susp即,输入了ctl-z的suspend键。那么SIGTSTP被发送给进程。
网上查到:SIGTSTP和SIGSTOP的唯一区别:
将进程暂停是SIGTSTP的默认action,用户可以自定义一其handler,而将进程暂停是SIGSTOP的定死的action,用户不能修改。此外,二者没什么差别,都使用SIGCONT来讲进程重新激活。
因为我们可以捕捉SIGTSTP信号,所以对于一些程序,它在被suspend的时候,她要保留当前control terminal的状态,当重新执行的时候,她要恢复control terminal的状态,因为他被暂停后,control terminal可能被别的进程使用而将control terminal的状态改变,(我们知道,一般情况下,一个进程将其标准输出和输入都设置为control terminal,对于像vi这样的程序,它在屏幕上的显示内容,应当被保存起来)所以它需要将其保存起来。
同时还应该注意的是,我们修改了SIGTSTP的handler之后,还是要在handler内部将该handler复原,然后重新触发SIGTSTP信号,来触发系统的默认处理的,这样才能将进程给suspend。
下面是例子:
#include "apue.h"
#define BUFFSIZE 1024
static void sig_tstp(int);
int
main(void)
{
int n;
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 ... */
}