1 信号的概念
信号是软件中断,由系统内核产生;
不可靠信号 : 指 信号可能会被丢失——一个信号发生了,但进程却决不会知道这一点;
可靠信号相关术语 : 信号产生(硬件异常或软件条件等),信号传送(内核在相关进程表置上标志),信号在两者之间称为信号未决,进程可以选用“信号递送阻塞”。如果为进程产生了一个选择为阻塞的信号,而且对该信号的动作是系统默认动作或捕捉该信号,则该信号处于未决状态,当处于未决状态的信号有多个时,Unix下一般在解除该信号阻塞后在信号处理函数中只处理一次;
SIGINT: 中断信号 SIGSEGV:存储访问出错 SIGQUIT: 退出信号 SIGCHLD: 子进程中止信号
系统对信号的基本操作:(三种)
1)忽略该信号;(SIGKILL和SIGSTOP信号不能忽略,这是超级用户杀死进程的有效方法)
2)捕捉该信号;
3)默认操作
2 信号函数
#define SIG_ERR (void (*)())-1
#define SIG_DFL (void (*)())0
#define SIG_IGN (void (*)())1
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
alarm(int nsec); 超时函数,超时产生一个SIGALRM信号
pause();挂起当前进程,直到信号处理函数返回;
信号集相关函数
int sigemptyset(sigset_st e t)* ;
int sigfillset(sigset_st e t)* ;
int sigaddset(sigset_ts e t,* int s i g n o) ;
int sigdelset(sigset_ts e t,* int s i g n o) ;
上面四个函数返回:若成功则为0,若出错则为-1
int sigismember(const sigset_s et t, *int s i g n o)
int sigprocmask(inht o w, const sigset_ts e *t, sigset_t o* s e t) ;
返回:若成功则为0,若出错则为-1
h o w 说明
S I G _ B L O C K :该该进程新的信号屏蔽字是其当前信号屏蔽字和s e t指向信号集的并集。s e t包含了我们希望阻塞的附加信号
S I G _ U N B L O C K: 该该进程新的信号屏蔽字是其当前信号屏蔽字和s e t所指向信号集的交集。s e t包含了我们希望解除阻塞的信号
S I G _ S E T M A S K 该该进程新的信号屏蔽是s e t指向的值如果s e t是个空指针,则不改变该进程的信号屏蔽字, h o w的值也无意义。
注意:如果在调用s i g p r o c m a s k后有任何未决的、不再阻塞的信号,则在s i g p r o c m a s k返回前,至少将其中之一递送给该进程。(相当解阻塞即时生效)
int sigpending(sigset_st e t)* ; 返回对于调用进程被阻塞不能递送和当前未决的信号集。该信号集通过s e t参数返回。
int sigaction(int signo, const struct sigactioan *act,struct sigactiono *oldact) ;
struct sigaction {
void (*sa_handler)(); /* addr of signal handler,or SIG_IGN, or SIG_DFL */
sigset_t sa_mask; /* additional signals to block */
int sa_flags; /* signal options, Table 10-5 */
} ;
int sigsuspend(const sigset_st * mask) ;
返回:-1, errno设置为E I N T R
该函数用在设置暂时信号屏蔽字,在该函数返回后(条件是捕捉处理完信号),屏蔽字恢复先前值;
下面是一段使用该函数的例子,用来保护某段关键代码不受SIGINT信号影响;
sigset newmask,oldmask,zeromask;
if(signal(SIGINT,sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
sigemptyset(&newmask);sigempty(&zeromask);
sigaddset(&newmask,SIGINT);
sigprocmask(SIG_BLOCK,&newmask,&oldmask);
/*critical region of code*/
.......
/* 恢复进程老的屏蔽字,若不这样作,阻塞的SIGINT可能会给进程带来额外操作*/
sigsuspend(&zeromask);
sigprocmask(SIG_SETMASK,&lodmask,NULL);
exit(0);